Archived
Merge pull request 'refactor(provision): Phase 3 — remove legacy host-keys/ fallback' (#59) from worktree-phase0-provision-ordering-fix into main
Check NixOS configurations / eval-hosts (push) Successful in 10m23s
Check NixOS configurations / eval-hosts (push) Successful in 10m23s
Merge PR #59: Phase 3 — remove legacy host-keys/ fallback
This commit was merged in pull request #59.
This commit is contained in:
@@ -8,9 +8,12 @@
|
||||
# script -- there's no multi-gigabyte image to transfer afterward. The first
|
||||
# time a node doesn't have that repo path yet, it's bootstrapped: cloned from
|
||||
# this checkout's own `origin` remote, then scripts/codex-setup.sh installs
|
||||
# the build tooling (Nix, etc.). Every run after that just `git pull`s it and
|
||||
# copies over the locally-managed host-keys/ (gitignored, so a git pull
|
||||
# alone wouldn't carry it) before building.
|
||||
# the build tooling (Nix, etc.). Every run after that just `git pull`s it.
|
||||
# SSH host keys are stored as clan vars (vars/per-machine/<target>/openssh/,
|
||||
# committed and sops-encrypted) -- the script decrypts them locally and
|
||||
# copies only the two files for this target to the node's host-keys/ before
|
||||
# building. A target with no clan var is an error (generate one first with
|
||||
# scripts/secrets/sync-host-keys.sh <target>).
|
||||
#
|
||||
# --node (default: $PROXMOX_HOST, see scripts/env.sh) picks which of the two
|
||||
# LAN Proxmox nodes this runs against: production, pve1.sweet.home
|
||||
@@ -497,27 +500,27 @@ sync_args=("$flake_target")
|
||||
[[ "$dry_run" -eq 1 ]] && sync_args+=(--dry-run)
|
||||
bash "$sync_keys" "${sync_args[@]}"
|
||||
|
||||
# If sync-host-keys.sh changed .sops.yaml or secrets/, those changes must be
|
||||
# committed and pushed before the remote `git pull` below picks them up --
|
||||
# the PVE node builds from whatever HEAD is checked out there, not the local
|
||||
# working tree. Detect uncommitted changes and block until the operator
|
||||
# confirms they've pushed, so the build never runs against a stale flake.
|
||||
# If sync-host-keys.sh changed .sops.yaml, secrets/, or vars/per-machine/,
|
||||
# those changes must be committed and pushed before the remote `git pull`
|
||||
# below picks them up -- the PVE node builds from whatever HEAD is checked
|
||||
# out there, not the local working tree. Uncommitted clan vars or sops
|
||||
# recipients mean the image builds fine but the host cannot decrypt its
|
||||
# secrets on first boot. Block until the operator confirms they've pushed.
|
||||
if [[ "$dry_run" -eq 0 ]]; then
|
||||
_sops_dirty="$(git -C "$repo_root" status --porcelain -- .sops.yaml secrets/ 2>/dev/null || true)"
|
||||
if [[ -n "$_sops_dirty" ]]; then
|
||||
_dirty="$(git -C "$repo_root" status --porcelain -- .sops.yaml secrets/ vars/per-machine/ 2>/dev/null || true)"
|
||||
if [[ -n "$_dirty" ]]; then
|
||||
echo
|
||||
echo "==> COMMIT + PUSH REQUIRED before the remote build can succeed:"
|
||||
echo " sync-host-keys.sh modified .sops.yaml / secrets/ to register the"
|
||||
echo " new host's sops recipient. The PVE node builds from the git-tracked"
|
||||
echo " flake, so these changes must be committed and pushed first -- otherwise"
|
||||
echo " the image build will succeed but the host cannot decrypt secrets on"
|
||||
echo " first boot (its age key isn't in the encrypted secrets files yet)."
|
||||
echo " Uncommitted changes in .sops.yaml, secrets/, or vars/per-machine/."
|
||||
echo " The PVE node builds from the git-tracked flake, so these changes"
|
||||
echo " must be committed and pushed first -- otherwise the image build will"
|
||||
echo " succeed but the host cannot decrypt its secrets on first boot."
|
||||
echo
|
||||
git -C "$repo_root" status --short -- .sops.yaml secrets/ || true
|
||||
git -C "$repo_root" status --short -- .sops.yaml secrets/ vars/per-machine/ || true
|
||||
echo
|
||||
read -rp " Commit and push those changes, then press Enter to continue (Ctrl-C to abort): "
|
||||
fi
|
||||
unset _sops_dirty
|
||||
unset _dirty
|
||||
fi
|
||||
|
||||
# --- VMID: pick one, and refuse to touch anything that already exists ---
|
||||
@@ -643,36 +646,34 @@ ensure_remote_repo() {
|
||||
}
|
||||
|
||||
# --- sync host key to the node ---------------------------------------------
|
||||
# Clan-managed keys live in vars/per-machine/ (committed, sops-encrypted),
|
||||
# so they arrive on the node via `git pull`. But the build scripts expect a
|
||||
# plaintext key file in host-keys/ (NIXOS_HOST_KEYS_DIR for LXC, or
|
||||
# --pre-format-files for VM). For clan keys, decrypt locally and scp just the
|
||||
# two files for this target; for legacy host-keys/ entries, scp the whole dir.
|
||||
# SSH host keys are stored as clan vars (vars/per-machine/<target>/openssh/).
|
||||
# Decrypt locally and scp just the two files for this target to the node's
|
||||
# host-keys/ directory, where the remote build script picks them up via
|
||||
# NIXOS_HOST_KEYS_DIR (LXC) or --pre-format-files (VM). A target with no
|
||||
# clan var is an error -- generate one first with sync-host-keys.sh.
|
||||
sync_remote_host_keys() {
|
||||
echo
|
||||
echo "==> Syncing host key for ${flake_target} to ${node}..."
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
if clan_ssh_key_exists "$flake_target" "$repo_root"; then
|
||||
echo "[dry-run] would decrypt clan SSH key for ${flake_target} and copy to ${ssh_target}:${remote_repo_dir}/host-keys/"
|
||||
else
|
||||
echo "[dry-run] would copy ${repo_root}/host-keys/ to ${ssh_target}:${remote_repo_dir}/host-keys/"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
ssh "$ssh_target" "mkdir -p '${remote_repo_dir}/host-keys'"
|
||||
if clan_ssh_key_exists "$flake_target" "$repo_root"; then
|
||||
if ! clan_ssh_key_exists "$flake_target" "$repo_root"; then
|
||||
echo "ERROR: no clan SSH key found for ${flake_target}" >&2
|
||||
echo " (expected: ${repo_root}/vars/per-machine/${flake_target}/openssh/ssh_host_ed25519_key/secret)" >&2
|
||||
echo " Generate one first: bash scripts/secrets/sync-host-keys.sh ${flake_target}" >&2
|
||||
exit 1
|
||||
fi
|
||||
local tmpdir
|
||||
tmpdir="$(mktemp -d)"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '${tmpdir}'" RETURN
|
||||
echo " Decrypting clan SSH key for ${flake_target}..."
|
||||
clan_decrypt_ssh_key "$flake_target" "$repo_root" "$tmpdir"
|
||||
ssh "$ssh_target" "mkdir -p '${remote_repo_dir}/host-keys'"
|
||||
scp -p "${tmpdir}/${flake_target}_ssh_host_ed25519_key" \
|
||||
"${tmpdir}/${flake_target}_ssh_host_ed25519_key.pub" \
|
||||
"${ssh_target}:${remote_repo_dir}/host-keys/"
|
||||
else
|
||||
scp -pr "${repo_root}/host-keys/." "${ssh_target}:${remote_repo_dir}/host-keys/"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- build (or reuse an image already on the node) ------------------------
|
||||
|
||||
Reference in New Issue
Block a user