CoursesSOPSAdvanced

SOPS in GitOps

Flux & Argo decrypt at apply.

Advanced14 min · lesson 9 of 12

SOPS is the most common answer to the GitOps secrets problem: the whole desired state lives in Git, yet secrets cannot be plaintext there. With SOPS, you commit the encrypted secret files, and the GitOps controller decrypts them at apply time using a key it holds in-cluster — so plaintext never touches the repo, and the decryption happens only inside the cluster that needs it. Both major GitOps tools support this natively.

SOPS DECRYPTION IN GITOPS
1Commit ciphertext
ENC[...] secret files in Git
2Controller reconciles
Flux kustomize-controller / Argo CD
3Decrypt in-cluster
age Secret or cloud KMS it holds
4Apply to cluster
plaintext exists only transiently
Plaintext never touches the repo; the controller's key is a fleet-wide boundary, so hold it as tight RBAC or KMS.
flux kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
spec:
path: ./apps
decryption:
provider: sops
secretRef: { name: sops-age } # the age/KMS key Flux decrypts with
# Git holds ENC[...] secrets; the kustomize-controller decrypts them at apply

Flux and Argo CD

Flux has first-class SOPS support in its kustomize-controller — point it at a decryption key (an age key stored as a Secret, or a cloud KMS it can call) and it decrypts SOPS files during reconciliation. Argo CD does it via a plugin or a Kustomize/Helm SOPS integration (KSOPS, helm-secrets). Either way the pattern is identical: ciphertext in Git, the controller’s key decrypts in-cluster, plaintext exists only transiently at apply. This is exactly the approach the Flux and Argo CD courses referenced.

The trust therefore concentrates in the controller’s decryption key: whoever can read it (or the cluster it lives in) can decrypt every secret the controller handles. Keep the key as a tightly-restricted Secret, or better, use a cloud KMS so the raw key never rests in the cluster and access is IAM-scoped and audited. This is the same conclusion as every SOPS scenario — the key is the boundary — now applied to a cluster-wide, always-on decryptor.

The GitOps controller’s SOPS key decrypts everything it manages
In GitOps, the decryption key held by Flux/Argo is a fleet-wide secret: it can decrypt every SOPS file the controller reconciles. Protect it accordingly — a locked-down Secret with tight RBAC, or a cloud KMS key the controller calls (so the key never sits in-cluster), with access scoped and audited. A leaked controller key exposes all your GitOps-managed secrets at once.