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
|
# 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
|
# 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
|
# 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
|
# the build tooling (Nix, etc.). Every run after that just `git pull`s it.
|
||||||
# copies over the locally-managed host-keys/ (gitignored, so a git pull
|
# SSH host keys are stored as clan vars (vars/per-machine/<target>/openssh/,
|
||||||
# alone wouldn't carry it) before building.
|
# 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
|
# --node (default: $PROXMOX_HOST, see scripts/env.sh) picks which of the two
|
||||||
# LAN Proxmox nodes this runs against: production, pve1.sweet.home
|
# 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)
|
[[ "$dry_run" -eq 1 ]] && sync_args+=(--dry-run)
|
||||||
bash "$sync_keys" "${sync_args[@]}"
|
bash "$sync_keys" "${sync_args[@]}"
|
||||||
|
|
||||||
# If sync-host-keys.sh changed .sops.yaml or secrets/, those changes must be
|
# If sync-host-keys.sh changed .sops.yaml, secrets/, or vars/per-machine/,
|
||||||
# committed and pushed before the remote `git pull` below picks them up --
|
# those changes must be committed and pushed before the remote `git pull`
|
||||||
# the PVE node builds from whatever HEAD is checked out there, not the local
|
# below picks them up -- the PVE node builds from whatever HEAD is checked
|
||||||
# working tree. Detect uncommitted changes and block until the operator
|
# out there, not the local working tree. Uncommitted clan vars or sops
|
||||||
# confirms they've pushed, so the build never runs against a stale flake.
|
# 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
|
if [[ "$dry_run" -eq 0 ]]; then
|
||||||
_sops_dirty="$(git -C "$repo_root" status --porcelain -- .sops.yaml secrets/ 2>/dev/null || true)"
|
_dirty="$(git -C "$repo_root" status --porcelain -- .sops.yaml secrets/ vars/per-machine/ 2>/dev/null || true)"
|
||||||
if [[ -n "$_sops_dirty" ]]; then
|
if [[ -n "$_dirty" ]]; then
|
||||||
echo
|
echo
|
||||||
echo "==> COMMIT + PUSH REQUIRED before the remote build can succeed:"
|
echo "==> COMMIT + PUSH REQUIRED before the remote build can succeed:"
|
||||||
echo " sync-host-keys.sh modified .sops.yaml / secrets/ to register the"
|
echo " Uncommitted changes in .sops.yaml, secrets/, or vars/per-machine/."
|
||||||
echo " new host's sops recipient. The PVE node builds from the git-tracked"
|
echo " The PVE node builds from the git-tracked flake, so these changes"
|
||||||
echo " flake, so these changes must be committed and pushed first -- otherwise"
|
echo " must be committed and pushed first -- otherwise the image build will"
|
||||||
echo " the image build will succeed but the host cannot decrypt secrets on"
|
echo " succeed but the host cannot decrypt its secrets on first boot."
|
||||||
echo " first boot (its age key isn't in the encrypted secrets files yet)."
|
|
||||||
echo
|
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
|
echo
|
||||||
read -rp " Commit and push those changes, then press Enter to continue (Ctrl-C to abort): "
|
read -rp " Commit and push those changes, then press Enter to continue (Ctrl-C to abort): "
|
||||||
fi
|
fi
|
||||||
unset _sops_dirty
|
unset _dirty
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- VMID: pick one, and refuse to touch anything that already exists ---
|
# --- VMID: pick one, and refuse to touch anything that already exists ---
|
||||||
@@ -643,36 +646,34 @@ ensure_remote_repo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- sync host key to the node ---------------------------------------------
|
# --- sync host key to the node ---------------------------------------------
|
||||||
# Clan-managed keys live in vars/per-machine/ (committed, sops-encrypted),
|
# SSH host keys are stored as clan vars (vars/per-machine/<target>/openssh/).
|
||||||
# so they arrive on the node via `git pull`. But the build scripts expect a
|
# Decrypt locally and scp just the two files for this target to the node's
|
||||||
# plaintext key file in host-keys/ (NIXOS_HOST_KEYS_DIR for LXC, or
|
# host-keys/ directory, where the remote build script picks them up via
|
||||||
# --pre-format-files for VM). For clan keys, decrypt locally and scp just the
|
# NIXOS_HOST_KEYS_DIR (LXC) or --pre-format-files (VM). A target with no
|
||||||
# two files for this target; for legacy host-keys/ entries, scp the whole dir.
|
# clan var is an error -- generate one first with sync-host-keys.sh.
|
||||||
sync_remote_host_keys() {
|
sync_remote_host_keys() {
|
||||||
echo
|
echo
|
||||||
echo "==> Syncing host key for ${flake_target} to ${node}..."
|
echo "==> Syncing host key for ${flake_target} to ${node}..."
|
||||||
if [[ "$dry_run" -eq 1 ]]; then
|
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/"
|
||||||
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
|
return
|
||||||
fi
|
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
|
||||||
local tmpdir
|
echo " (expected: ${repo_root}/vars/per-machine/${flake_target}/openssh/ssh_host_ed25519_key/secret)" >&2
|
||||||
tmpdir="$(mktemp -d)"
|
echo " Generate one first: bash scripts/secrets/sync-host-keys.sh ${flake_target}" >&2
|
||||||
# shellcheck disable=SC2064
|
exit 1
|
||||||
trap "rm -rf '${tmpdir}'" RETURN
|
|
||||||
echo " Decrypting clan SSH key for ${flake_target}..."
|
|
||||||
clan_decrypt_ssh_key "$flake_target" "$repo_root" "$tmpdir"
|
|
||||||
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
|
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/"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- build (or reuse an image already on the node) ------------------------
|
# --- build (or reuse an image already on the node) ------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user