SOPS in GitOps
Flux & Argo decrypt at apply.
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.
apiVersion: kustomize.toolkit.fluxcd.io/v1kind: Kustomizationspec:path: ./appsdecryption:provider: sopssecretRef: { 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.