Archived
fix(provision): block build until sops changes are committed, guard missing host keys
Three ordering-related fixes to the Proxmox provisioning flow: 1. prepare-host-key.sh: make idempotent -- if the key already exists, print a note and exit 0 instead of erroring. The caller (create-proxmox-resource.sh) already guards standalone calls, but the script itself should be safe to run directly on a host that was already keyed. 2. create-proxmox-resource.sh: after sync-host-keys.sh updates .sops.yaml / secrets/, detect uncommitted changes and block with a prompt until the operator confirms they've committed and pushed. The PVE node's git pull only picks up committed+pushed state; without this gate, a new host's sops recipient is missing from the secrets files the image build uses, so the host can't decrypt secrets on first boot. 3. create-proxmox-resource.sh: add an explicit existence check for the host key in both the LXC and VM remote build heredocs, before it's passed as --pre-format-files / NIXOS_HOST_KEYS_DIR input. Gives a clear error pointing at sync-host-keys.sh instead of a raw `cp: cannot stat` from disko deep in the build. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -502,6 +502,29 @@ 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 [[ "$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
|
||||
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
|
||||
git -C "$repo_root" status --short -- .sops.yaml secrets/ || true
|
||||
echo
|
||||
read -rp " Commit and push those changes, then press Enter to continue (Ctrl-C to abort): "
|
||||
fi
|
||||
unset _sops_dirty
|
||||
fi
|
||||
|
||||
# --- VMID: pick one, and refuse to touch anything that already exists ---
|
||||
echo
|
||||
if [[ -z "$vmid" ]]; then
|
||||
@@ -707,6 +730,12 @@ cd "$repo_dir"
|
||||
# right after a successful install.
|
||||
. scripts/lib/nix-bootstrap.sh
|
||||
ensure_nix_profile
|
||||
if [[ ! -f "host-keys/${target}_ssh_host_ed25519_key" ]]; then
|
||||
echo "ERROR: host-keys/${target}_ssh_host_ed25519_key not found in ${repo_dir}." >&2
|
||||
echo "Generate the key locally (scripts/secrets/sync-host-keys.sh ${target})" >&2
|
||||
echo "and ensure it was synced here before starting the build." >&2
|
||||
exit 1
|
||||
fi
|
||||
NIXOS_HOST_KEYS_DIR="$(pwd)/host-keys" nix build --impure \
|
||||
--no-use-registries --no-accept-flake-config "${NIX_OPTS[@]}" \
|
||||
".#nixosConfigurations.${target}.config.system.build.tarball" \
|
||||
@@ -747,6 +776,12 @@ declare -a NIX_OPTS=()
|
||||
cd "$repo_dir"
|
||||
. scripts/lib/nix-bootstrap.sh
|
||||
ensure_nix_profile
|
||||
if [[ ! -f "host-keys/${target}_ssh_host_ed25519_key" ]]; then
|
||||
echo "ERROR: host-keys/${target}_ssh_host_ed25519_key not found in ${repo_dir}." >&2
|
||||
echo "Generate the key locally (scripts/secrets/sync-host-keys.sh ${target})" >&2
|
||||
echo "and ensure it was synced here before starting the build." >&2
|
||||
exit 1
|
||||
fi
|
||||
nix build --no-use-registries --no-accept-flake-config "${NIX_OPTS[@]}" \
|
||||
".#nixosConfigurations.${target}.config.system.build.diskoImagesScript" \
|
||||
--out-link "result-${target}"
|
||||
|
||||
@@ -41,8 +41,9 @@ 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
|
||||
echo "Key already exists: ${keyfile}"
|
||||
echo "Reusing the existing key. Remove it first if you want to regenerate."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
nix_extra_opts
|
||||
|
||||
Reference in New Issue
Block a user