Guardrails That Stop It
- No Plaintext in Git: Any file under
flux/secrets/must be encrypted. sops-ageSecret: Must exist in theflux-systemnamespace for decryption to work.no-secretsHook: Local pre-commit hook that blocks files likekubeconfigor.env.flux-kustomize-validateHook: Ensures your secret wiring is syntactically correct before commit.
Safe Workflow (Step-by-Step)
- Verify Prerequisites: Ensure
sopsandageare installed locally. - Check for Key: Ensure the
sops-agesecret exists in your cluster:kubectl -n flux-system get secret sops-age - Create Secret: Use the helper script to create and encrypt your secret. On the local cluster the target is
local- the directory your key can encrypt for - and the Secret lands indevelop:(On the platform, operators run the same helper withscripts/sops-encrypt-secret.sh local lab-secretdevelop/staging/production; those directories are encrypted for the platform key.) - Update Kustomization: Add the new
.yamlfile toflux/secrets/local/kustomization.yaml. - Commit and Push: Add the encrypted file and the kustomization update to Git. Flux (
secrets-local) picks it up on the next reconcile.
CI/Logs Guardrails
- Never print secrets: Avoid
echo $SECRETin CI pipelines. - No verbose traces: Do not use
set -xin scripts that handle secrets. - Check existence only: Verify that a secret exists without dumping its values:
kubectl -n develop get secret backend-secrets -o name
Key Rotation
To rotate your Age keys and re-encrypt secrets:
- Generate a new key:
age-keygen -o age-new.agekey. - Update
.sops.yaml: Replace the old public key with the new one. - Re-encrypt: Run
sops rotate --in-place <file>for every secret. - Update Cluster: Delete and recreate the
sops-agesecret influx-system.
This builds on: GitOps (Chapter 03) — the Flux reconciliation you just learned is what decrypts and applies the secret. This enables: CI/CD guardrails (Chapter 05) — hooks and CI stop plaintext secrets before they reach Git.