Archived
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5f749daa9 | ||
|
|
adaf53d647 | ||
|
|
01679f1639 | ||
|
|
8f4c88347d | ||
|
|
2526b2dca7 | ||
|
|
5e2ff76cf7 | ||
|
|
5db41b1166 | ||
|
|
67752fb1e8 | ||
|
|
0853952269 |
@@ -27,12 +27,13 @@ machines when deployed.
|
||||
template for a *real* host — every other host uses sops-nix
|
||||
(`hashedPasswordFile`, see "Security Notes" in `README.md`). Flag any *new*
|
||||
secret-like string you encounter instead of committing it.
|
||||
- `host-keys/` is gitignored — locally-generated *private* SSH host keys
|
||||
for the auto-installer and non-LXC hosts (see `docs/auto-installer.md`).
|
||||
Never commit its contents; if `git status` ever shows it as trackable,
|
||||
something is wrong. Deployed LXC hosts use clan vars
|
||||
(`vars/per-machine/<target>/openssh/`, committed and sops-encrypted)
|
||||
instead — those ARE tracked by git and belong in the repo.
|
||||
- `host-keys/` is gitignored — used only by the auto-installer's own
|
||||
environment for pre-seeding non-LXC host keys before first boot (see
|
||||
`docs/auto-installer.md`). Never commit its contents; if `git status`
|
||||
ever shows it as trackable, something is wrong. All deployed hosts use
|
||||
clan vars (`vars/per-machine/<target>/openssh/`, committed and
|
||||
sops-encrypted) for their SSH host keys — those ARE tracked by git and
|
||||
belong in the repo.
|
||||
|
||||
### Two Proxmox nodes: `pve1.sweet.home` (production) and `pve-test.sweet.home` (sandbox)
|
||||
|
||||
@@ -206,11 +207,11 @@ instead of copying it.
|
||||
- `scripts/secrets/sync-host-keys.sh` — generates/registers SSH host keys
|
||||
and their `.sops.yaml`/`secrets/*.yaml` recipients for flake targets,
|
||||
idempotently (`--all`, `<target>`, `--remove`, `--regenerate-all-keys`,
|
||||
all with `--dry-run`). For lxc-* targets it stores keys as clan vars
|
||||
(`vars/per-machine/<target>/openssh/`, committed and sops-encrypted);
|
||||
for other targets it uses the gitignored `host-keys/` directory. The
|
||||
primary tool for provisioning a new host's secrets access — see
|
||||
"Creating a new machine" in `docs/auto-installer.md`.
|
||||
all with `--dry-run`). Stores keys as clan vars
|
||||
(`vars/per-machine/<target>/openssh/`, committed and sops-encrypted) for
|
||||
all flake targets. The primary tool for provisioning a new host's
|
||||
secrets access — see "Creating a new machine" in
|
||||
`docs/auto-installer.md`.
|
||||
- `scripts/secrets/prepare-host-key.sh` — narrower predecessor: generates a
|
||||
key by an arbitrary name without touching `.sops.yaml`. Still useful to
|
||||
pre-generate a key before its flake target exists yet, since
|
||||
|
||||
@@ -72,8 +72,8 @@ nix eval --json .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]'
|
||||
| `modules/common/` | Shared NixOS config, Home Manager, aliases imported by every host |
|
||||
| `modules/nix-cache/` | Binary cache and remote builder client/server modules |
|
||||
| `modules/installer/` | Auto-installer environment (ISO, also served as PXE netboot) — see `docs/auto-installer.md` |
|
||||
| `host-keys/` | Gitignored, locally-generated SSH host keys for the auto-installer (non-LXC hosts) — see `docs/auto-installer.md`. LXC hosts use clan vars (`vars/per-machine/<target>/openssh/`) instead |
|
||||
| `vars/per-machine/` | Clan vars: committed, sops-encrypted SSH host keys for deployed LXC hosts; read by `create-proxmox-resource.sh` at deploy time |
|
||||
| `host-keys/` | Gitignored; only used by the auto-installer environment for pre-seeding SSH host keys before first boot — see `docs/auto-installer.md`. All deployed hosts use clan vars (`vars/per-machine/<target>/openssh/`) instead |
|
||||
| `vars/per-machine/` | Clan vars: committed, sops-encrypted SSH host keys for all deployed hosts; read by `create-proxmox-resource.sh` at deploy time |
|
||||
| `docs/` | Operational notes for cache, builders, lock updates, boot services, the auto-installer, and Proxmox image builds |
|
||||
| `scripts/` | Codex setup, validation, host-key, release-bump, and Proxmox resource helpers |
|
||||
|
||||
@@ -163,8 +163,9 @@ sops-nix-everywhere: it has a hardcoded login password instead (no stable
|
||||
per-boot host key for sops-nix to derive from on ephemeral media) — see
|
||||
"Host keys" in `docs/auto-installer.md` for why, and how the private keys it
|
||||
*does* pre-seed for target hosts stay out of git via the gitignored
|
||||
`host-keys/` directory. Deployed LXC hosts instead use clan vars
|
||||
(`vars/per-machine/<target>/openssh/`, committed and sops-encrypted).
|
||||
`host-keys/` directory. All deployed hosts use clan vars
|
||||
(`vars/per-machine/<target>/openssh/`, committed and sops-encrypted) for
|
||||
their SSH host keys.
|
||||
|
||||
This repository's git *history* still contains secrets committed before this
|
||||
migration (see `remove-sensetive-info-refactor.md`) — those are being
|
||||
|
||||
@@ -11,17 +11,16 @@
|
||||
# sync-host-keys.sh --regenerate-all-keys Remove and freshly regenerate
|
||||
# every locally-managed key.
|
||||
#
|
||||
# "Generate/register" is idempotent and additive only: an existing
|
||||
# host-keys/ file is never touched, and .sops.yaml only ever gains an
|
||||
# anchor/alias it doesn't already have -- safe to re-run any time, e.g.
|
||||
# right after adding a new host to flake.nix.
|
||||
# "Generate/register" is idempotent and additive only: an existing clan
|
||||
# var is never overwritten, and .sops.yaml only ever gains an anchor/alias
|
||||
# it doesn't already have -- safe to re-run any time, e.g. right after
|
||||
# adding a new host to flake.nix.
|
||||
#
|
||||
# --remove and --regenerate-all-keys only ever operate on anchors that have
|
||||
# a corresponding host-keys/<name>_ssh_host_ed25519_key file. Anchors
|
||||
# without one (&admin, and any anchor for an already-deployed host whose
|
||||
# real /etc/ssh key was registered by hand, e.g. &docker/&server/&nix-cache
|
||||
# today) are never listed, removed, or regenerated -- this tooling only
|
||||
# ever touches keys it itself manages.
|
||||
# --remove and --regenerate-all-keys only ever operate on anchors that
|
||||
# have a corresponding clan var (vars/per-machine/<name>/openssh/) or
|
||||
# host-keys/ file. Anchors without either (&admin) are never listed,
|
||||
# removed, or regenerated -- this tooling only ever touches keys it itself
|
||||
# manages.
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
@@ -56,13 +55,14 @@ Usage: $0 --all [--dry-run]
|
||||
<flake-target> Same, for just one target (e.g. lxc-server).
|
||||
Reports if it already has one.
|
||||
--remove Interactively pick one locally-managed key to
|
||||
remove from .sops.yaml and host-keys/.
|
||||
remove from .sops.yaml and vars/per-machine/
|
||||
(or host-keys/ for legacy keys).
|
||||
--regenerate-all-keys Remove every locally-managed key and generate
|
||||
fresh replacements for every current flake
|
||||
target. Destructive -- requires typed
|
||||
fresh clan-var replacements for every current
|
||||
flake target. Destructive -- requires typed
|
||||
confirmation.
|
||||
--dry-run Combine with any of the above: print what would
|
||||
change (host-keys/ files, .sops.yaml anchors and
|
||||
change (clan vars, .sops.yaml anchors and
|
||||
key_groups, which secrets/*.yaml would be
|
||||
re-encrypted) without touching anything. No keys
|
||||
generated, no files written, no sops calls,
|
||||
@@ -135,10 +135,17 @@ discover_targets() {
|
||||
}
|
||||
|
||||
locally_managed_hosts() {
|
||||
for f in "$keydir"/*_ssh_host_ed25519_key.pub; do
|
||||
[[ -e "$f" ]] || continue
|
||||
basename "$f" _ssh_host_ed25519_key.pub
|
||||
done
|
||||
{
|
||||
for f in "$keydir"/*_ssh_host_ed25519_key.pub; do
|
||||
[[ -e "$f" ]] || continue
|
||||
basename "$f" _ssh_host_ed25519_key.pub
|
||||
done
|
||||
local d
|
||||
for d in "${repo_root}/vars/per-machine"/*/openssh/ssh_host_ed25519_key/secret; do
|
||||
[[ -f "$d" ]] || continue
|
||||
basename "$(dirname "$(dirname "$(dirname "$d")")")"
|
||||
done
|
||||
} | sort -u
|
||||
}
|
||||
|
||||
add_keys_json="[]"
|
||||
@@ -308,7 +315,7 @@ cmd_remove() {
|
||||
local hosts
|
||||
mapfile -t hosts < <(locally_managed_hosts)
|
||||
if [[ "${#hosts[@]}" -eq 0 ]]; then
|
||||
echo "No locally-managed keys in host-keys/ -- nothing to remove."
|
||||
echo "No locally-managed keys found (checked host-keys/ and vars/per-machine/) -- nothing to remove."
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -317,7 +324,9 @@ cmd_remove() {
|
||||
for host in "${hosts[@]}"; do
|
||||
local registered="not registered in .sops.yaml"
|
||||
grep -qE "^ - &${host} age1" "$sops_yaml" && registered="registered in .sops.yaml"
|
||||
printf ' %d) %s (%s)\n' "$i" "$host" "$registered"
|
||||
local where="host-keys/"
|
||||
clan_ssh_key_exists "$host" "$repo_root" && where="clan-vars"
|
||||
printf ' %d) %s [%s, %s]\n' "$i" "$host" "$where" "$registered"
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
@@ -334,7 +343,7 @@ cmd_remove() {
|
||||
local target="${hosts[$((choice - 1))]}"
|
||||
|
||||
if [[ "$dry_run" -ne 1 ]]; then
|
||||
read -rp "Really remove '${target}'? Its host-keys/ files will be deleted and it will lose access to every secrets file it can currently decrypt. (y/N): " confirm
|
||||
read -rp "Really remove '${target}'? Its key files will be deleted and it will lose access to every secrets file it can currently decrypt. (y/N): " confirm
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
echo "Cancelled."
|
||||
return
|
||||
@@ -347,11 +356,13 @@ cmd_remove() {
|
||||
apply_edit_plan "$plan"
|
||||
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
echo "[dry-run] would delete host-keys/${target}_ssh_host_ed25519_key(.pub)."
|
||||
echo "[dry-run] would delete host-keys/${target}_ssh_host_ed25519_key(.pub) if present."
|
||||
echo "[dry-run] would delete vars/per-machine/${target}/openssh/ if present."
|
||||
echo "[dry-run] Nothing was changed. Re-run without --dry-run to apply this."
|
||||
else
|
||||
rm -f "${keydir}/${target}_ssh_host_ed25519_key" "${keydir}/${target}_ssh_host_ed25519_key.pub"
|
||||
echo "Removed host-keys/${target}_ssh_host_ed25519_key(.pub)."
|
||||
rm -rf "${repo_root}/vars/per-machine/${target}/openssh"
|
||||
echo "Removed key for ${target} (host-keys/ and/or vars/per-machine/ as applicable)."
|
||||
echo
|
||||
echo "Review the diff, then commit and push."
|
||||
fi
|
||||
@@ -361,7 +372,7 @@ cmd_regenerate_all() {
|
||||
local hosts
|
||||
mapfile -t hosts < <(locally_managed_hosts)
|
||||
if [[ "${#hosts[@]}" -eq 0 ]]; then
|
||||
echo "No locally-managed keys in host-keys/ -- nothing to regenerate."
|
||||
echo "No locally-managed keys found (checked host-keys/ and vars/per-machine/) -- nothing to regenerate."
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -390,8 +401,8 @@ cmd_regenerate_all() {
|
||||
apply_edit_plan "$plan"
|
||||
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
echo "[dry-run] would delete ${#hosts[@]} host-keys/ file pair(s)."
|
||||
echo "[dry-run] would then generate fresh replacements for the same hosts"
|
||||
echo "[dry-run] would delete ${#hosts[@]} key pair(s) from host-keys/ and/or vars/per-machine/."
|
||||
echo "[dry-run] would then generate fresh clan vars replacements for the same hosts"
|
||||
echo "[dry-run] (not simulated further here -- run without --dry-run, or"
|
||||
echo "[dry-run] preview a specific target with: $0 <target> --dry-run)."
|
||||
echo
|
||||
@@ -403,8 +414,9 @@ cmd_regenerate_all() {
|
||||
local host
|
||||
for host in "${hosts[@]}"; do
|
||||
rm -f "${keydir}/${host}_ssh_host_ed25519_key" "${keydir}/${host}_ssh_host_ed25519_key.pub"
|
||||
rm -rf "${repo_root}/vars/per-machine/${host}/openssh"
|
||||
done
|
||||
echo "Removed ${#hosts[@]} host-keys/ file pair(s)."
|
||||
echo "Removed ${#hosts[@]} key pair(s)."
|
||||
|
||||
echo
|
||||
echo "Regenerating fresh keys for every current flake target..."
|
||||
|
||||
Reference in New Issue
Block a user