Archived
sops-nix (in the nixos flake) derives each host's age decryption key from its own /etc/ssh/ssh_host_ed25519_key at activation time, which runs before systemd would otherwise generate that key on first boot (sshd-keygen is a plain systemd service gated behind multi-user.target; activation scripts run earlier). Without pre-seeding, secrets -- including the login password -- fail to decrypt on a fresh install's very first boot. - scripts/prepare-host-key.sh: run on the admin workstation before an install, generates the host's ed25519 keypair and prints the exact steps to register its derived age key in nixos/.sops.yaml and re-encrypt the affected secrets/*.yaml files. - common.nix's auto-install.sh: after disko mounts /mnt and before nixos-install, installs a pre-seeded key from /root/host-keys/ into /mnt/etc/ssh/ if present, otherwise warns and asks for confirmation before continuing without one. - installer.nix now imports common.nix (previously only proxmox-lxc.nix did), so the ISO/netboot path used for EFI VM installs gets the same auto-install.sh and pre-seed check, not just the LXC path. - Also fixes a pre-existing stray backtick in the disko invocation that broke auto-install.sh's bash syntax entirely, independent of this change (found while rendering the script to verify the new logic). README.md documents the new pre-flight workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
66 lines
2.5 KiB
Bash
Executable File
66 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Generates a new machine's SSH host key ahead of installing it, so
|
|
# sops-nix (in the `nixos` flake) has something to derive an age key
|
|
# from before the target ever boots.
|
|
#
|
|
# Why this is needed: sops-nix derives each host's decryption key from
|
|
# its own /etc/ssh/ssh_host_ed25519_key at *activation* time, but that
|
|
# activation runs before systemd would otherwise generate this key on
|
|
# first boot (sshd-keygen is a normal systemd service gated behind
|
|
# multi-user.target; activation scripts run earlier than that). Without
|
|
# pre-seeding, secrets — including the root/nixos login password — fail
|
|
# to decrypt on the machine's very first boot.
|
|
#
|
|
# This script only touches your admin workstation and the `nixos` repo's
|
|
# .sops.yaml (it never contacts the target machine). Run it, follow the
|
|
# printed next steps, then use the resulting key with the auto-install.sh
|
|
# prompt (see common.nix) when you actually install the new machine.
|
|
set -euo pipefail
|
|
|
|
hostname="${1:?usage: scripts/prepare-host-key.sh <hostname> [path-to-nixos-repo]}"
|
|
nixos_repo="${2:-../nixos}"
|
|
sops_yaml="${nixos_repo}/.sops.yaml"
|
|
|
|
if [[ ! -f "$sops_yaml" ]]; then
|
|
echo "ERROR: $sops_yaml not found. Pass the nixos repo path as the 2nd argument." >&2
|
|
exit 1
|
|
fi
|
|
|
|
keydir="$(dirname "$0")/../host-keys"
|
|
mkdir -p "$keydir"
|
|
keyfile="${keydir}/${hostname}_ssh_host_ed25519_key"
|
|
|
|
if [[ -f "$keyfile" ]]; then
|
|
echo "ERROR: $keyfile already exists. Remove it first if you want to regenerate." >&2
|
|
exit 1
|
|
fi
|
|
|
|
nix-shell -p openssh ssh-to-age --run "
|
|
set -euo pipefail
|
|
ssh-keygen -t ed25519 -N '' -C '${hostname}' -f '${keyfile}' >/dev/null
|
|
age_pub=\$(ssh-to-age -i '${keyfile}.pub')
|
|
cat <<EOF
|
|
|
|
Generated: ${keyfile}(.pub)
|
|
|
|
=== 1. Add this line under `keys:` in ${sops_yaml} ===
|
|
- &${hostname} \${age_pub}
|
|
|
|
=== 2. Add *${hostname} to whichever creation_rules key_groups this host needs ===
|
|
(e.g. secrets/common.yaml always; add a per-host secrets/${hostname}.yaml
|
|
block too if this host will get its own secrets, same pattern as
|
|
nix-cache/server.)
|
|
|
|
=== 3. Re-encrypt every secrets file you just added it to ===
|
|
nix-shell -p sops --run 'sops updatekeys ${nixos_repo}/secrets/common.yaml'
|
|
|
|
=== 4. Commit + push the nixos repo so the flake build picks up the new recipient ===
|
|
|
|
=== 5. When you boot the installer on the new machine, scp the key in ===
|
|
scp ${keyfile}{,.pub} root@<target-ip>:/root/host-keys/
|
|
|
|
Then continue with /etc/auto-install.sh as normal — it will find the
|
|
pre-seeded key and install it before running nixos-install.
|
|
EOF
|
|
"
|