From 14c849633ec6e7f4d47193dd0c4aa1e1297c668d Mon Sep 17 00:00:00 2001 From: File Magic Date: Wed, 19 Aug 2026 10:14:26 -0400 Subject: [PATCH] modules/secrets.nix [hosts]: scope agenix keys and enable NAT66 --- 13-inch-thin-cannon/configuration.nix | 12 ++++++++-- README.md | 23 +++++++++++++++++-- justfile | 14 ++++++++--- modules/secrets.nix | 21 ++++------------- secrets/wireguard-key-thick-black-cannon.age | Bin 222 -> 0 bytes thick-black-cannon/configuration.nix | 10 ++++++++ thick-black-cannon/wireguard.nix | 20 ---------------- 7 files changed, 57 insertions(+), 43 deletions(-) delete mode 100644 secrets/wireguard-key-thick-black-cannon.age delete mode 100644 thick-black-cannon/wireguard.nix diff --git a/13-inch-thin-cannon/configuration.nix b/13-inch-thin-cannon/configuration.nix index de73dc3..383b221 100644 --- a/13-inch-thin-cannon/configuration.nix +++ b/13-inch-thin-cannon/configuration.nix @@ -21,6 +21,13 @@ ] ++ lib.optional (builtins.pathExists ./wireguard.nix) ./wireguard.nix; + # This secret is host-specific; do not declare it in the shared secrets + # module, or other hosts will try to decrypt it during activation. + age.secrets."wireguard-key-13-inch-thin-cannon" = { + file = ../secrets/wireguard-key-13-inch-thin-cannon.age; + mode = "400"; + }; + nix.settings.experimental-features = [ "nix-command" "flakes" @@ -180,8 +187,9 @@ # Enable touchpad support (enabled default in most desktopManager). # services.xserver.libinput.enable = true; - # Define a user account. Set its password with - # `just set-file-magic-password` after provisioning agenix. + # Define a user account. Provision its yescrypt password with + # `just set-file-magic-password` after provisioning agenix. SSH remains + # key-only below; the password is for local console and PAM authentication. # nushell is only for file_magic: `users.defaultUserShell` would also change # root's login shell, breaking POSIX-sh remote commands (ssh, sudo, scripts). users = { diff --git a/README.md b/README.md index 38dc09b..140db9a 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,33 @@ NUR-only packaged add-ons are not installed by the declarative profile. sudo nixos-rebuild switch --flake .#"" ``` -Set the `file_magic` account password using an agenix-encrypted yescrypt hash: +Provision the `file_magic` account password as an agenix-encrypted yescrypt hash: ```sh just set-file-magic-password ``` +This password is intentionally not accepted over SSH: the installed host uses +key-only SSH authentication. It remains useful for local console login and +sudo/PAM authentication. The target does not change `sshd` settings. + +If password SSH is required, enable it explicitly in the installed host: + +```nix +services.openssh.settings = { + PasswordAuthentication = true; + KbdInteractiveAuthentication = true; +}; +``` + +Prefer enabling this only on a trusted network or WireGuard interface. SSH +keys, preferably FIDO2-backed `ed25519-sk` keys, provide a better remote-login +security boundary than passwords. + Set `AGE_RECIPIENT` to the target host's SSH public key when provisioning from -another machine. +another machine. For a fresh install, provision after the target has generated +its host key; encrypting to the build machine's host key will leave the target +unable to decrypt the secret. ## 13-Inch ISO diff --git a/justfile b/justfile index 0460d67..45b625c 100644 --- a/justfile +++ b/justfile @@ -17,6 +17,11 @@ ovmf: # Full lifecycle: build the ISO, then test live boot, installation, and boot up: build test-iso +# Decrypt an age secret with this machine's SSH host identity. +# Usage: `just decrypt-secret secrets/example.age` +decrypt-secret secret: + nix shell nixpkgs#age --command sudo age --decrypt -i /etc/ssh/ssh_host_ed25519_key -o - "{{secret}}" + # Encrypt a yescrypt hash for the file_magic account with agenix. Set # AGE_RECIPIENT to the target host's SSH public key when running remotely. set-file-magic-password: @@ -44,7 +49,8 @@ set-file-magic-password: hash="$(printf '%s' "$password" | mkpasswd -m yescrypt -s)" unset password password_repeat rules_file="$(mktemp)" - trap 'rm -f "$rules_file"' EXIT + hash_file="$(mktemp)" + trap 'rm -f "$rules_file" "$hash_file"' EXIT cat >"$rules_file" <"$hash_file" + unset hash + RULES="$rules_file" nix develop --command agenix -e "$secret_file" <"$hash_file" + echo "Encrypted $secret_file (local console/PAM password; SSH password auth remains disabled)" # Boot the generated ISO in QEMU (OVMF UEFI) and verify it test-iso: ovmf diff --git a/modules/secrets.nix b/modules/secrets.nix index 38d8936..46beddd 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -10,22 +10,11 @@ in { identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - secrets = - { - wireguard-key-13-inch-thin-cannon = { - file = ../secrets/wireguard-key-13-inch-thin-cannon.age; - mode = "400"; - }; - wireguard-key-thick-black-cannon = { - file = ../secrets/wireguard-key-thick-black-cannon.age; - mode = "400"; - }; - } - // lib.optionalAttrs (builtins.pathExists fileMagicPassword) { - file_magic-password = { - file = fileMagicPassword; - mode = "400"; - }; + secrets = lib.optionalAttrs (builtins.pathExists fileMagicPassword) { + file_magic-password = { + file = fileMagicPassword; + mode = "400"; }; + }; }; } diff --git a/secrets/wireguard-key-thick-black-cannon.age b/secrets/wireguard-key-thick-black-cannon.age deleted file mode 100644 index 85e3379214149c9fe968e2fe1c41b00a5ab0e55d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR2FFfuhYv{dlV%+xom3OB9Db_>!Da!yGx z$#*I84Jr!CG&CslOp9>Nam@_&EHv%im830Ex22-{%auvRh3^GQ#Us@?Puz~o|8-FN&?irZngd_= Y73MCVTCwK(&h19)=1+}3U1lx-0K?HxzyJUM diff --git a/thick-black-cannon/configuration.nix b/thick-black-cannon/configuration.nix index 6178713..f5e8361 100644 --- a/thick-black-cannon/configuration.nix +++ b/thick-black-cannon/configuration.nix @@ -51,6 +51,16 @@ # Enable networking networking.networkmanager.enable = true; + # Libvirt gives the IPv6-only Kubernetes guests private ULA addresses. NAT66 + # is required because the Wi-Fi uplink routes only its delegated prefix, not + # the guests' fd00::/8 source addresses. + networking.nat = { + enable = true; + enableIPv6 = true; + externalInterface = "wlp7s0"; + internalIPv6s = ["fd00::/8"]; + }; + # Set your time zone. time.timeZone = "America/New_York"; diff --git a/thick-black-cannon/wireguard.nix b/thick-black-cannon/wireguard.nix deleted file mode 100644 index 061eb34..0000000 --- a/thick-black-cannon/wireguard.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ - config, - pkgs, - ... -}: { - networking.wireguard.interfaces = { - wg0 = { - ips = ["10.0.0.2/24"]; - privateKeyFile = config.age.secrets."wireguard-key-thick-black-cannon".path; - peers = [ - { - publicKey = "CHANGE_ME"; - allowedIPs = ["10.0.0.0/24"]; - endpoint = "CHANGE_ME:51820"; - persistentKeepalive = 25; - } - ]; - }; - }; -} -- 2.51.2