# .sops.yaml — SOPS creation rules for the platform repo (ADR-0007, R-SEC-01). # # ───────────────────────────────────────────────────────────────────────────── # CANONICAL LOCATION: this is the ONE .sops.yaml, at the REPOSITORY ROOT. SOPS # discovers it by walking UP from the file being encrypted, so a root file governs # every secret under platform/**, apps/**, catalog/**, and secrets/**. # There is deliberately NO second copy under bootstrap/sops/ — a duplicate there # would be discovered first for files in that subtree and shadow this one (that # footgun is why the earlier bootstrap/sops/.sops.yaml was removed). # ───────────────────────────────────────────────────────────────────────────── # # HOW ENCRYPTION WORKS HERE: # - Only committed secrets are encrypted; plaintext never enters git. # - `encrypted_regex` encrypts ONLY the value fields (data/stringData), leaving # keys and structure in cleartext → readable, reviewable diffs (ADR-0007). # - `age` recipient below is the PUBLIC key from age-keygen.sh. Filling it is a # bootstrap step; the matching PRIVATE key is installed in-cluster as the # `sops-age` Secret (age-key-secret.md) so Flux can decrypt at reconcile. # # TO ENCRYPT A SECRET (operator, not agents): # sops --encrypt --in-place path/to/secret.sops.yaml # # picks up the age recipient + rules below automatically. creation_rules: # Platform + app Secrets. Convention: encrypted files are named `*.sops.yaml` # or live under a `secrets/` directory anywhere in the tree. - path_regex: (^|/)(platform|apps|catalog)/.*(secret|sops)\.ya?ml$ encrypted_regex: "^(data|stringData)$" # age PUBLIC recipient (from age-keygen.sh) — safe to commit. To rotate, see # bootstrap/sops/age-key-secret.md (add new recipient, re-encrypt, drop old). age: "age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg" - path_regex: (^|/)secrets/.*\.ya?ml$ encrypted_regex: "^(data|stringData)$" # same age PUBLIC recipient as above. age: "age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg" # OpenTofu runtime secrets (dotenv). Holds the R2 S3 keys, the state-encryption # passphrase, and the Proxmox API token that tf.sh injects into the provider's # ENVIRONMENT (never a tofu variable/state). Dotenv, so `sops exec-env` / tf.sh # can export cleanly; NO encrypted_regex here → SOPS encrypts EVERY value (the # keys stay cleartext for reviewable diffs). Encrypted to the same age recipient. - path_regex: (^|/)infra/tofu/secrets\.sops\.env$ age: "age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg"