Greenfield spec set for a GitOps-driven PaaS+IaaS home platform: vision & requirements (R-* IDs), architecture, 14 domain specs, 11 ADRs, roadmap (phases + workstreams), and AI-agent coordination (roles, protocol, definition-of-done, task board). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
1.7 KiB
1.7 KiB
ADR-0007 — Secrets: SOPS + age
- Status: Accepted
- Date: 2026-08-15
- Serves: R-SEC-01, R-GITOPS-01
- Supersedes: —
Context
Secrets (VPN keys, DNS API token, SMTP creds, service passwords, backup-target creds) must live in git for GitOps but MUST NOT be plaintext. The engine is Flux (ADR-0004), which decrypts SOPS natively.
Decision
Encrypt secrets in git with SOPS using age recipients; Flux decrypts in-cluster at reconciliation via an age private key bootstrapped as a Kubernetes Secret. Plaintext secrets never enter git or logs. Secret rotation = re-encrypt + commit; Flux rolls it out (restart triggered by checksum annotation where needed).
Alternatives considered
- Sealed Secrets (Bitnami) — solid; one-way encryption to a cluster key. SOPS chosen for native Flux integration, multi-recipient/age simplicity, and readable, reviewable encrypted diffs.
- External Secrets Operator + external vault (Vault/cloud SM) — stronger for large orgs but adds an external dependency and operational weight not justified for a single-operator home platform. May be revisited via superseding ADR if a real external secret store is introduced.
- Plaintext + private repo — rejected outright (R-SEC-01).
Consequences
- Secrets are versioned, encrypted, and reconciled with the rest of GitOps state.
- The age private key bootstrap is a sanctioned out-of-band step (documented; one of the few non-GitOps actions, 07).
- Key custody/rotation for the age key itself must be documented; losing it blocks decryption.
- No secret material may appear in agent output, PRs, or logs (AGENTS.md §5).