Security & Secrets Management (SOPS + age)¶
This project follows a "secure by default" approach appropriate for production-style systems.
Threat model (practical)¶
- secrets must not be committed in plaintext
- CI/CD must not leak keys into logs
- runtime services should receive secrets via Kubernetes / environment injection
Secrets management approach¶
- secrets are encrypted at rest using SOPS
- the encryption backend is age
- encrypted files (
*.enc.*) are safe to store in git - plaintext secrets are generated only at deploy/runtime boundaries
Examples of encrypted assets:
- .env.enc
- Kubernetes secrets manifests (secret.enc.yaml)
- Helm values (values-dev.enc.yaml)
- registry tokens (gitlab-registry-token.enc.yaml)
CI/CD handling¶
- CI decrypts secrets only in the minimal scope required for deployment
- secrets are injected via protected variables / masked CI variables
- decrypted files are treated as ephemeral artifacts and must not persist
Best practices checklist¶
- [ ] SOPS/age private keys are stored only in protected CI variables
- [ ] CI logs do not print decrypted values
- [ ] Kubernetes secrets are namespace-scoped and access-controlled
- [ ] least privilege for registry tokens and service accounts
- [ ] rotation procedure documented (see Runbooks)
Next: ADRs¶
Architectural security decisions are recorded in ADR: - ADR-0004 — Secrets Management