7 Commits
Author SHA1 Message Date
jakman85andClaude Opus 5 8059297036 fix(devcontainer): bake wg + qrencode into the image instead of splitting the VPN procedure across host and container
gate / gate (pull_request) Successful in 1m53s
gate / conformance (pull_request) Has been skipped
Operator correction: "sop, wg, and any other tool requirement is supposed to be
baked into the devcontainer."

My previous commit discovered that `wg` existed only on the host, `sops` only in
the container, and `qrencode` on neither -- and fixed it the wrong way, by
splitting every step of the key procedure across the boundary and telling the
operator to `dnf install qrencode` on their workstation. That breaks CLAUDE.md §5
and the devcontainer README's "Don't install the toolchain on the host", produces
a procedure that cannot be reproduced in CI, and is miserable to follow.

wireguard-tools + qrencode are now distro packages in the Containerfile. Both are
in Fedora 44's repos (wireguard-tools 1.0.20260223 -- the same upstream version as
the image this component runs -- and qrencode 4.1.1), unpinned like every other
dnf package there: the pinned thing is the Fedora base, and neither is a gate tool
whose version changes what green means.

Three things got SIMPLER rather than merely relocated, which is the tell that the
rule was right:

  * Step 2 is one pipeline in one shell -- `sops set ... "$(wg genkey)"` writes the
    key straight into the already-encrypted document. No staged copy in .cache, no
    `*.key`-suffix warning, no sha256 comparison to prove the right bytes landed.
  * new-peer.sh derives the server public key from wg-server-key.sops.yaml itself
    (`sops -d --extract | wg pubkey`), so there is no local key copy to keep in
    step with the encrypted one, and no magic host path it must live at.
  * `.cache/` is gitignored at the repo root (mirroring infra/ansible/.gitignore),
    giving the container a persistent non-committable scratch dir. new-peer.sh
    writes profiles to .cache/wg-peers/ -- necessary because the repo bind-mount is
    the container's only persistent read-write mount, so a profile in /tmp there is
    gone before it can reach a desktop. Its blanket "refuse to write inside the
    checkout" guard is now a `git check-ignore` test of the real property.

Verified by execution, not reasoning: the image rebuilds; wg/qrencode/sops all
resolve in it; `sops -d | wg pubkey` runs in one shell; new-peer.sh refuses the
REPLACE-ME placeholder with an actionable message; and a full run with a throwaway
server key renders a correct profile at 0600 under a 0700 gitignored dir, prints
the QR, and refuses a non-ignored destination inside the repo.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-10-06 00:48:32 -05:00
jakman85andClaude Opus 4.8 ba72725a4e OS upgrade complete: Debian 12->13 (trixie) baseline + re-provision role fixes
All 3 k3s nodes re-provisioned to Debian 13 (kernel 6.12) via immutable tofu -replace,
one at a time, primary/leader last (secondary-join to avoid cluster-init split-brain).
- variables.tf image defaults -> debian-13-generic (generic, not genericcloud)
- k3s_server: ensure /etc/rancher/k3s exists (fresh-node re-provision fix)
- gitignore vendored ansible collections (installed for re-provision)

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-30 11:12:53 -05:00
jakman85andClaude Opus 4.8 216bea2a16 tofu: move secrets into committed SOPS/age file + tf.sh wrapper
Replace the gitignored plaintext infra/tofu/.r2.env and backend.hcl with a
single committed, SOPS/age-encrypted dotenv (secrets.sops.env) plus a thin
wrapper (tf.sh), so tofu runs with no manual secret entry and secrets live
encrypted in git like the repo's other secrets.

- .sops.yaml: creation rule encrypting infra/tofu/secrets.sops.env (all values)
  to the existing age recipient.
- secrets.sops.env: encrypted, PLACEHOLDER values only. Holds R2 S3 keys, the
  state-encryption passphrase (TF_STATE_PASSPHRASE scalar), and the Proxmox API
  token/endpoint. Operator fills real values via `sops`.
- tf.sh: sops exec-env decrypts the dotenv, exports PROXMOX_VE_*/AWS_*, builds
  the multi-line TF_ENCRYPTION HCL from TF_STATE_PASSPHRASE, and runs tofu
  (injecting -backend-config=backend.r2.hcl on init). Proxmox token stays env-only,
  never a tofu variable/state.
- backend.r2.hcl: committed non-secret R2 bucket/key/endpoint (account id is not
  a credential), passed to `tofu init`.
- Retire .r2.env/backend.hcl(.example): drop the committed templates; keep the
  gitignore lines as a safety net for leftover local plaintext.
- Update backend.tf/README/REMOTE-STATE for the new day-2 flow and DR story
  (repo + age key is sufficient).

Verified: placeholder file round-trips sops -e/-d with the repo age key; tf.sh
exports the expected VAR NAMES and builds valid TF_ENCRYPTION HCL (stub tofu, no
real plan/secrets).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-27 19:07:52 -05:00
jakman85andClaude Opus 4.8 2919a1d72e chore: gitignore .claude/ (agent worktrees pollute lint + git add -A)
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-27 17:19:42 -05:00
jakman85andClaude Opus 4.8 485b9e3888 infra(tofu): scaffold off-cluster R2 remote state (encrypted)
Local-only tfstate meant losing the workstation would strand a rebuild (apply
would try to recreate the 3 live nodes). Move state to Cloudflare R2, which sits
OUTSIDE the Proxmox->VM->cluster->Gitea chain, so a full cluster rebuild can still
read it; encrypted at rest via OpenTofu native AES-GCM.

Adds a partial s3 backend (R2 skip-flags), gitignored backend.hcl/.r2.env for the
account-specific + secret bits, their .example templates, and a migration+DR runbook.
Locking (use_lockfile) deferred to an OpenTofu >=1.10 bump (1.9.0 lacks it).
Migration (tofu init -migrate-state) runs once the operator provisions the R2 bucket.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-27 15:57:12 -05:00
jakman85andClaude Opus 4.8 a2392a4a43 tofu(proxmox): API-only native cloud-init; move node baseline to Ansible node_baseline role
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-25 10:55:48 -05:00
jakman85andClaude Opus 4.8 253b6600f4 Initial skeleton: home-network-k3s implementation repo
Phase 0 foundation shell (read-only spec at ../home-network-k3s). Top-level
tree + rules; workstream agents fill their subtrees on feature branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-15 23:41:43 -05:00