10. Configure SOPS and AGE for secret encryption¶
10.1. Basic SOPS / AGE setup¶
Create an AGE key pair. The generated file (
age.agekeyin the example below) contains the secret key (store its content safely)
→ age-keygen -o age.agekey Public key: age1ttax...REDACTED → cat age.agekey # created: 2025-06-25T21:10:45-07:00 # public key: age1ttax...REDACTED AGE-SECRET-KEY-1N...REDACTED
Use the sops command to encrypt a secret:
→ cat mysecrets.yaml --- apiVersion: v1 kind: Secret metadata: name: mysecrets type: Opaque stringData: username: "alice" password: "supersecret" → sops --age=age1t...REDACTED \ --encrypt \ --encrypted-regex '^(data|stringData)$' \ --in-place mysecrets.yaml → cat mysecrets.yaml apiVersion: v1 kind: Secret metadata: name: mysecrets type: Opaque stringData: username: ENC[AES256_GCM,data:UicDDU0=,iv:JwuhuMYAsALZnAcqslMD9XwlykUyFv2bljIqQYiGKMs=,tag:As2FLh4Ao+lZSTEjxlxq4A==,type:str] password: ENC[AES256_GCM,data:751c4RypvRiADwc=,iv:sta8Qknev6t06oA6a65HvAbuS1GA47peXYV/Ynvci/w=,tag:mK9FGEbi143hlWQHBSAskA==,type:str] sops: age: - recipient: age1t...REDACTED enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkYjU4ZFdQS3lzNzBKSmJK ... ...
Adding a
.sops.yamlconfig file to the repo, we can avoid typing some of the parameters each time we invokesops:
→ cat .sops.yaml creation_rules: - path_regex: .*.yaml encrypted_regex: ^(data|stringData)$ age: age1t...REDACTED # the sops command above can be now reduced to: → sops --encrypt --in-place mysecrets.yaml
To decrypt in the terminal, add the AGE key to
$HOME/.config/sops/age/keys.txtand usesops decrypt(Ref. ([sops] section “Encrypting using age”) for more details)
→ cat age.agekey >> $HOME/.config/sops/age/keys.txt → sops decrypt mysecrets.yaml
10.2. Using SOPS/AGE with Flux¶
Flux guide: [flux-sops-1]
1. Add the AGE secret key to the k8s cluster as a secret, in the flux-system namespace
→ cat age.agekey | kubectl create secret generic sops-age \ --namespace=flux-system \ --from-file=age.agekey=/dev/stdin secret/sops-age created → kubectl -n flux-system get secrets sops-age -o yaml apiVersion: v1 data: age.agekey: REDACTED kind: Secret ... #(to view the decrypted value) → kubectl -n flux-system \ get secrets sops-age -o yaml \ | yq ".data.\"age.agekey\"" \ | base64 -d
2. The sops-age secret need to be specified in the Flux Kustomization for the component that uses the key for encryption, by adding a decryption: key in the spec, for example:
→ cat clusters/my-cluster/infra.yaml --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: infra-monitoring namespace: flux-system spec: interval: 1h retryInterval: 1m timeout: 5m sourceRef: kind: GitRepository name: flux-system path: ./infra/monitoring prune: true wait: true # Decryption configuration decryption: provider: sops secretRef: name: sops-age
3. Add a .sops.yaml file to the repository root, containing the public key
(ref. above section) (to make sure we use the same age key when encrypting secrets)
10.3. Using SOPS/AGE with Flux Helm Releases¶
Flux guide: [flux-sops-2]
When using sops to encrypt values to be used in Flux Helm releases, the guide recommend to use a Kustomize secret generator (to trigger a Helm release upgrade every time the encrypted secret values change)