Skip to content

Sealed Secrets

GitOps means your cluster's desired state lives in Git, but you cannot commit plain Kubernetes Secret objects there; they are only base64-encoded, not encrypted. We recommend Sealed Secrets for this. It encrypts a secret so it can be safely committed to a Git repository, and only your cluster can decrypt it.

How it works

A controller in your cluster holds a private key. You encrypt secrets against the matching public key using the kubeseal CLI, producing a SealedSecret resource. ArgoCD applies the SealedSecret like any other manifest, and the controller decrypts it in-cluster into a regular Secret that your pods consume. The plaintext never leaves your machine in a form anyone but your cluster can read.

Workflow

Write a normal Secret manifest (do not commit this file), then seal it:

# Create a Secret manifest locally (not committed)
kubectl create secret generic db-credentials \
  --namespace my-app \
  --from-literal=password='s3cr3t' \
  --dry-run=client -o yaml > secret.yaml

# Seal it against the cluster's public key
kubeseal --format yaml < secret.yaml > sealed-secret.yaml

Commit sealed-secret.yaml to your repository and let ArgoCD deploy it. The resulting Secret appears in the my-app namespace for your pods to mount or reference as environment variables.

kubeseal fetches the public key from the controller in your cluster using your kubeconfig. If you run it offline, fetch the certificate once with kubeseal --fetch-cert and pass it with --cert.

A SealedSecret is encrypted for a specific namespace and name by default, so move or rename it only by re-sealing.