This repository has been archived on 2026-07-30. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
nixos/scripts/prepare-host-key.sh
T
rootandClaude Sonnet 5 7e51168d1b
Check NixOS configurations / eval-hosts (pull_request) Failing after 11m29s
Deduplicate reusable shell code in scripts/ into scripts/lib/
Three chunks of copy-pasted logic were drifting across scripts/*.sh:
- codex-setup.sh and codex-maintenance.sh each carried an identical
  NIX_CONFIG bootstrap + ensure_nix_profile() -> scripts/lib/nix-bootstrap.sh
- sync-host-keys.sh and prepare-host-key.sh each ran the same
  ssh-keygen/ssh-to-age nix-shell invocations -> scripts/lib/ssh-host-keys.sh
  (prepare-host-key.sh now also calls env.sh's nix_extra_opts before using
  them, closing a gap where it alone skipped the nix-cache reachability
  check env.sh exists for)
- the "list nixosConfigurations attrNames" / "get one target's hostName"
  nix eval pattern was repeated across codex-setup.sh, codex-maintenance.sh,
  sync-host-keys.sh and create-proxmox-resource.sh (the latter twice, in
  its own --list and --host lookup) -> scripts/lib/nix-eval.sh, which also
  centralizes the --no-use-registries --no-accept-flake-config flag pair
  used on every such call

Verified against the real flake/node config (nix is available here):
create-proxmox-resource.sh --list for both --type lxc/vm, a full
--dry-run create, and prepare-host-key.sh generating and cleaning up a
real key/age-pubkey pair.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 10:35:49 +00:00

84 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Generates a new machine's SSH host key by an arbitrary name, before it
# necessarily has a flake target yet -- prints the .sops.yaml snippet to
# add by hand. For any host that already has a flake target,
# scripts/sync-host-keys.sh <target> does this same job plus the
# .sops.yaml/key_groups registration and re-encryption automatically; use
# this script only to pre-generate a key ahead of adding the flake target
# itself.
#
# Why a host key is needed at all: 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 this 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 modules/installer/common.nix) when you actually install the
# new machine.
set -euo pipefail
repo_root="$(cd "$(dirname "$0")/.." && pwd)"
# shellcheck source=env.sh
source "${repo_root}/scripts/env.sh"
# shellcheck source=lib/ssh-host-keys.sh
source "${repo_root}/scripts/lib/ssh-host-keys.sh"
hostname="${1:?usage: scripts/prepare-host-key.sh <hostname>}"
sops_yaml="${repo_root}/.sops.yaml"
if [[ ! -f "$sops_yaml" ]]; then
echo "ERROR: $sops_yaml not found — is this script still under nixos/scripts/?" >&2
exit 1
fi
keydir="${repo_root}/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_extra_opts
generate_host_ed25519_key "$hostname" "$keyfile"
age_pub="$(ssh_pubkey_to_age "${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 ${repo_root}/secrets/common.yaml'
=== 4. Commit + push this repo so the flake build picks up the new recipient ===
=== 5. Get the key onto the installer, one of two ways ===
a) Rebuild the installer image with all host-keys/ baked in (see
docs/auto-installer.md):
NIXOS_HOST_KEYS_DIR="${keydir}" nix build .#iso --impure
(or .#pxe — --impure is required since host-keys/ is gitignored and
flakes can't see it otherwise)
b) Or, for an image already built without keys, scp it in after boot:
scp ${keyfile}{,.pub} root@<target-ip>:/root/host-keys/
Then continue with /etc/auto-install.sh as normal — it checks
/etc/host-keys (baked in) before /root/host-keys (scp'd) and installs
whichever it finds before running nixos-install.
EOF