initial commit

This commit is contained in:
2025-05-12 23:25:39 -03:00
parent bf178e3caa
commit dc6f6894e6
95 changed files with 3922 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# Core functionality for every nix-darwin host
# NOTE(starter): Declare any darwin-specific, core configurations here.
{ }

View File

@@ -0,0 +1,103 @@
# FIXME(starter): modify this file and the other .nix files in `nix-config/hosts/common/core/` to declare
# settings that will occur across all hosts
# IMPORTANT: This is used by NixOS and nix-darwin so options must exist in both!
{
inputs,
outputs,
config,
lib,
pkgs,
isDarwin,
...
}:
let
platform = if isDarwin then "darwin" else "nixos";
platformModules = "${platform}Modules";
in
{
imports = lib.flatten [
inputs.home-manager.${platformModules}.home-manager
(map lib.custom.relativeToRoot [
"modules/common"
"modules/hosts/common"
"modules/hosts/${platform}"
"hosts/common/core/${platform}.nix"
#"hosts/common/core/sops.nix" # Core because it's used for backups, mail
"hosts/common/core/ssh.nix"
#"hosts/common/core/services" # uncomment this line if you add any modules to services directory
"hosts/common/users/primary"
"hosts/common/users/primary/${platform}.nix"
])
];
#
# ========== Core Host Specifications ==========
#
# FIXME(starter): modify the hostSpec options below to define values that are common across all hosts
# such as the username and handle of the primary user (see also `nix-config/hosts/common/users/primary`)
hostSpec = {
username = "panotaka";
handle = "panotaka";
# FIXME(starter): modify the attribute sets hostSpec will inherit from your nix-secrets.
# If you're not using nix-secrets then remove the following six lines below.
};
networking.hostName = config.hostSpec.hostName;
# System-wide packages, in case we log in as root
environment.systemPackages = [ pkgs.openssh ];
# Force home-manager to use global packages
home-manager.useGlobalPkgs = true;
# If there is a conflict file that is backed up, use this extension
home-manager.backupFileExtension = "bk";
#
# ========== Overlays ==========
#
nixpkgs = {
overlays = [
outputs.overlays.default
];
config = {
allowUnfree = true;
};
};
#
# ========== Nix Nix Nix ==========
#
nix = {
# This will add each flake input as a registry
# To make nix3 commands consistent with your flake
registry = lib.mapAttrs (_: value: { flake = value; }) inputs;
# This will add your inputs to the system's legacy channels
# Making legacy nix commands consistent as well, awesome!
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
settings = {
# See https://jackson.dev/post/nix-reasonable-defaults/
connect-timeout = 5;
log-lines = 25;
min-free = 128000000; # 128MB
max-free = 1000000000; # 1GB
trusted-users = [ "@wheel" ];
# Deduplicate and optimize nix store
auto-optimise-store = true;
warn-dirty = false;
allow-import-from-derivation = true;
experimental-features = [
"nix-command"
"flakes"
];
};
};
}

View File

@@ -0,0 +1,36 @@
# Core functionality for every nixos host
{ config, lib, ... }:
{
# Database for aiding terminal-based programs
environment.enableAllTerminfo = true;
# Enable firmware with a license allowing redistribution
hardware.enableRedistributableFirmware = true;
# This should be handled by config.security.pam.sshAgentAuth.enable
security.sudo.extraConfig = ''
Defaults lecture = never # rollback results in sudo lectures after each reboot, it's somewhat useless anyway
Defaults pwfeedback # password input feedback - makes typed password visible as asterisks
Defaults timestamp_timeout=120 # only ask for password every 2h
# Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
Defaults env_keep+=SSH_AUTH_SOCK
'';
#
# ========== Nix Helper ==========
#
# Provide better build output and will also handle garbage collection in place of standard nix gc (garbace collection)
# FIXME(starter): customize garbage collection rules as desired.
programs.nh = {
enable = true;
clean.enable = true;
clean.extraArgs = "--keep-since 20d --keep 20";
flake = "/home/user/${config.hostSpec.home}/nix-config";
};
#
# ========== Localization ==========
#
# FIXME(starter): customize localization values as desired.
i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
time.timeZone = lib.mkDefault "America/Edmonton";
}

View File

@@ -0,0 +1,9 @@
# Add your core services to the same directory as this default.nix file.
# They will automatically be imported below.
{
lib,
...
}:
{
imports = (lib.custom.scanPaths ./.);
}

11
hosts/common/core/ssh.nix Normal file
View File

@@ -0,0 +1,11 @@
{
lib,
pkgs,
...
}:
{
programs.ssh = lib.optionalAttrs pkgs.stdenv.isLinux {
startAgent = true;
enableAskPassword = true;
};
}

View File

@@ -0,0 +1,65 @@
# `...` is needed because dikso passes diskoFile
{
lib,
disk ? "/dev/vda",
withSwap ? false,
swapSize,
...
}:
{
disko.devices = {
disk = {
disk0 = {
type = "disk";
device = disk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = {
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,71 @@
# `...` is needed because dikso passes diskoFile
{
lib,
disk ? "/dev/vda",
withSwap ? false,
swapSize,
...
}:
{
disko.devices = {
disk = {
main = {
type = "disk";
device = disk;
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
#passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
};
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@swap" = lib.mkIf withSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = "${swapSize}G";
};
};
};
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,21 @@
# NOTE(starter): configure your audio needs as required.
{ pkgs, ... }:
{
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
wireplumber.enable = true;
jack.enable = true;
};
environment.systemPackages = builtins.attrValues {
inherit (pkgs)
playerctl # cli utility and lib for controlling media players
# pamixer # cli pulseaudio sound mixer
;
};
}

View File

@@ -0,0 +1,4 @@
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
{
services.desktopManager.plasma6.enable = true;
}

View File

@@ -0,0 +1,13 @@
# NOTE: This module is required for nixos-installer
{ config, ... }:
{
# Set a temp password for use by minimal builds like installer and iso
users.users.${config.hostSpec.username} = {
isNormalUser = true;
# This is a hashed version of the plain-text password "nixos" for use in the ISO. Even though,
# the password is known, we use `hashedPassword` here instead of `password` to mitigate
# occurrences of the latter not being used during build.
password = "password";
extraGroups = [ "wheel" ];
};
}

View File

@@ -0,0 +1,10 @@
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
{
services.displayManager = {
sddm.enable = true;
sddm.wayland = {
enable = true;
compositor = "kwin";
};
};
}

View File

@@ -0,0 +1,36 @@
{
config,
...
}:
let
# FIXME(starter): if you are not defining ports in your "soft" nix-secrets, you can
# replace the following line with: sshPort = 22;
# and substitute 22 with a custom port number if needed.
sshPort = 22;
in
{
services.openssh = {
enable = true;
ports = [ sshPort ];
settings = {
# Harden
PasswordAuthentication = false;
PermitRootLogin = "no";
# Automatically remove stale sockets
StreamLocalBindUnlink = "yes";
# Allow forwarding ports to everywhere
GatewayPorts = "clientspecified";
};
hostKeys = [
{
path = "/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
];
};
networking.firewall.allowedTCPPorts = [ sshPort ];
}

View File

@@ -0,0 +1,5 @@
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
{
services.xserver.desktopManager.xfce.enable = true;
services.xserver.desktopManager.xfce.enableScreensaver = false;
}

View File

@@ -0,0 +1,67 @@
# FIXME(starter): this is an example of how a secondary user called "exampleSecondUser" can be declared.
# NOTE that this file's parent directory matches the username!
# Modify the directory name and all instances of `exampleSecondUser` in this file to a real username to
# make use of this file. You'll also need to import this file in the relevant `nix-config/hosts/[platform]/[hostname]/default.nix`
# host file for the user to be created on the host.
# NOTE that this file also assumes you will be declaring the user's password via sops.
# .
# If you have no need for secondary users, simple delete this file and its parent directory, and ensure that
# your `nix-confitg/hosts/[platform]/[hostname]/default.nix` files do not import this file.
#
# Basic user for viewing exampleSecondUser
#
{
inputs,
lib,
pkgs,
config,
...
}:
let
hostSpec = config.hostSpec;
secretsSubPath = "passwords/exampleSecondUser";
in
{
# Decrypt passwords/exampleSecondUser to /run/secrets-for-users/ so it can be used to create the user
sops.secrets.${secretsSubPath}.neededForUsers = true;
users.mutableUsers = false; # Required for password to be set via sops during system activation!
users.users.exampleSecondUser = {
isNormalUser = true;
hashedPasswordFile = config.sops.secrets.${secretsSubPath}.path;
shell = pkgs.zsh; # default shell
extraGroups = [
"audio"
"video"
];
packages = [ pkgs.home-manager ];
};
}
# Import this user's personal/home configurations
// lib.optionalAttrs (inputs ? "home-manager") {
home-manager = {
extraSpecialArgs = {
inherit pkgs inputs;
hostSpec = config.hostSpec;
};
users.exampleSecondUser.imports = lib.flatten (
lib.optional (!hostSpec.isMinimal) [
(
{ config, ... }:
import (lib.custom.relativeToRoot "home/exampleSecondUser/${hostSpec.hostName}.nix") {
inherit
pkgs
inputs
config
lib
hostSpec
;
}
)
]
);
};
}

View File

@@ -0,0 +1,7 @@
# User config applicable only to darwin
{ config, ... }:
{
users.users.${config.hostSpec.username} = {
home = "/Users/${config.hostSpec.username}";
};
}

View File

@@ -0,0 +1,68 @@
# NOTE(starter): this is the primary user across all hosts. The username for primary is defined in hostSpec,
# and is declared in `nix-config/common/core/default.nix`
# User config applicable to both nixos and darwin
{
inputs,
pkgs,
config,
lib,
...
}:
let
hostSpec = config.hostSpec;
pubKeys = lib.filesystem.listFilesRecursive ./keys;
in
{
users.users.${hostSpec.username} = {
name = hostSpec.username;
shell = pkgs.bash; # default shell
# These get placed into /etc/ssh/authorized_keys.d/<name> on nixos
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
};
# Create ssh sockets directory for controlpaths when homemanager not loaded (i.e. isMinimal)
systemd.tmpfiles.rules =
let
user = config.users.users.${hostSpec.username}.name;
group = config.users.users.${hostSpec.username}.group;
in
# you must set the rule for .ssh separately first, otherwise it will be automatically created as root:root and .ssh/sockects will fail
[
"d /home/${hostSpec.username}/.ssh 0750 ${user} ${group} -"
"d /home/${hostSpec.username}/.ssh/sockets 0750 ${user} ${group} -"
];
# No matter what environment we are in we want these tools
programs.zsh.enable = true;
environment.systemPackages = [
pkgs.just
pkgs.rsync
];
}
# Import the user's personal/home configurations, unless the environment is minimal
// lib.optionalAttrs (inputs ? "home-manager") {
home-manager = {
extraSpecialArgs = {
inherit pkgs inputs;
hostSpec = config.hostSpec;
};
users.${hostSpec.username}.imports = lib.flatten (
lib.optional (!hostSpec.isMinimal) [
(
{ config, ... }:
import (lib.custom.relativeToRoot "home/${hostSpec.username}/${hostSpec.hostName}.nix") {
inherit
pkgs
inputs
config
lib
hostSpec
;
}
)
]
);
};
}

View File

@@ -0,0 +1 @@
Add your ssh public keys to this directory. E.g. id_foo.pub

View File

@@ -0,0 +1,44 @@
# User config applicable only to nixos
{
config,
lib,
pkgs,
...
}:
let
hostSpec = config.hostSpec;
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
in
{
users.mutableUsers = false; # Only allow declarative credentials; Required for password to be set via sops during system activation!
users.users.${hostSpec.username} = {
home = "/home/${hostSpec.username}";
isNormalUser = true;
password = "password";
extraGroups = lib.flatten [
"wheel"
(ifTheyExist [
"audio"
"video"
"docker"
"git"
"networkmanager"
"scanner" # for print/scan"
"lp" # for print/scan"
])
];
};
# No matter what environment we are in we want these tools for root, and the user(s)
programs.git.enable = true;
# root's ssh key are mainly used for remote deployment, borg, and some other specific ops
users.users.root = {
shell = pkgs.bash;
hashedPasswordFile = config.users.users.${hostSpec.username}.hashedPasswordFile;
hashedPassword = config.users.users.${hostSpec.username}.hashedPassword; # This comes from hosts/common/optional/minimal.nix and gets overridden if sops is working
openssh.authorizedKeys.keys = config.users.users.${hostSpec.username}.openssh.authorizedKeys.keys; # root's ssh keys are mainly used for remote deployment.
};
}