Sealed Secrets Management Kubernetes
Manage secrets securely with Bitnami Sealed Secrets on Kubernetes. Encrypt secrets for Git storage, cluster-scoped and namespace-scoped sealing.
π‘ Quick Answer: Use
kubesealto encrypt Kubernetes Secrets intoSealedSecretresources that are safe to store in Git. The Sealed Secrets controller in the cluster decrypts them back to regular Secrets. Only the clusterβs private key can decrypt β even you canβt read them after sealing.
The Problem
Kubernetes Secrets are base64-encoded (not encrypted) and canβt be stored in Git safely. Teams end up with Secrets managed outside of GitOps β manually applied, easily forgotten, and never version-controlled. Sealed Secrets solve this by encrypting secrets for Git storage.
The Solution
Install Sealed Secrets
# Install controller
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets \
--namespace kube-system
# Install kubeseal CLI
brew install kubeseal # or download binarySeal a Secret
# Create a regular secret (don't apply it)
kubectl create secret generic db-creds \
--from-literal=username=admin \
--from-literal=password=s3cret123 \
--dry-run=client -o yaml > secret.yaml
# Seal it
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# The sealed-secret.yaml is safe to commit to Git!
cat sealed-secret.yamlSealedSecret Resource
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-creds
namespace: production
spec:
encryptedData:
username: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
password: AgAR5VvPmB+KkLfS0aTzrcOTJRVtYhrk...
template:
metadata:
name: db-creds
namespace: production
type: OpaqueThe controller decrypts this into a regular Secret automatically.
Scoping Options
# Namespace-scoped (default) β only works in the specified namespace
kubeseal --scope namespace-wide < secret.yaml > sealed.yaml
# Cluster-scoped β works in any namespace
kubeseal --scope cluster-wide < secret.yaml > sealed.yaml
# Strict (default) β name AND namespace must match
kubeseal --scope strict < secret.yaml > sealed.yamlKey Rotation
# Fetch the current public key
kubeseal --fetch-cert > pub-cert.pem
# Controller rotates keys every 30 days automatically
# Old secrets remain decryptable (controller keeps old keys)
# Force re-encryption with new key
kubeseal --re-encrypt < sealed-secret.yaml > re-encrypted.yamlgraph LR
DEV[Developer] -->|kubeseal encrypt| SEALED[SealedSecret<br/>encrypted YAML]
SEALED -->|git push| GIT[Git Repository<br/>Safe to store β
]
GIT -->|ArgoCD sync| CLUSTER[Kubernetes Cluster]
CLUSTER --> CTRL[Sealed Secrets<br/>Controller]
CTRL -->|Decrypt with<br/>cluster private key| SECRET[Regular Secret<br/>available to pods]Backing Up the Sealing Key for Disaster Recovery
The controllerβs private key is the only thing that can decrypt every SealedSecret youβve ever committed β losing it without a backup means re-sealing every secret in Git from scratch:
# Backup β store this in a vault, NEVER in Git
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > sealed-secrets-master-key.yaml# Restore on a new/recovered cluster β apply the key BEFORE installing the controller
kubectl apply -f sealed-secrets-master-key.yaml
helm install sealed-secrets sealed-secrets/sealed-secrets --namespace kube-systemThe same export/apply works for sharing one key across multiple clusters, though per-environment keys (a separate public key per cluster) are usually the safer default β a leaked staging key then canβt decrypt production secrets.
GitOps Integration
# ArgoCD: point an Application at the directory of SealedSecret manifests
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {name: production-secrets, namespace: argocd}
spec:
project: default
source: {repoURL: https://github.com/myorg/k8s-configs, targetRevision: main, path: sealed-secrets/production}
destination: {server: https://kubernetes.default.svc, namespace: production}
syncPolicy: {automated: {prune: true, selfHeal: true}}Organize sealed secrets per environment so ArgoCD/Flux syncs the right set to the right cluster:
k8s-configs/
βββ sealed-secrets/
β βββ production/
β βββ staging/
β βββ development/A pre-commit hook catches the one mistake that defeats the whole point β committing a plain Secret instead of the sealed version:
#!/bin/bash
# .git/hooks/pre-commit
if git diff --cached --name-only | xargs grep -l "kind: Secret" 2>/dev/null | grep -v "SealedSecret"; then
echo "ERROR: Plain Kubernetes Secret detected! Seal it before committing."
exit 1
fiCommon Issues
βcannot fetch certificateβ error
The sealed-secrets controller isnβt running or the service isnβt accessible. Check: kubectl get pods -n kube-system | grep sealed-secrets.
Secret not decrypting in target namespace
Scope mismatch. By default, SealedSecrets are strict-scoped β name and namespace must match exactly what was used during sealing.
Best Practices
- Store SealedSecrets in Git β the whole point is GitOps-friendly secret management
- Backup the sealing keys β
kubectl get secret -n kube-system sealed-secrets-key* -o yaml > backup.yaml - Strict scope for production β prevents secrets from being used in wrong namespaces
- Re-encrypt periodically β run
kubeseal --re-encryptafter key rotation - Donβt commit the original Secret β only the SealedSecret goes in Git
Key Takeaways
- Sealed Secrets encrypt Kubernetes Secrets for safe Git storage
- Only the clusterβs private key can decrypt β kubeseal uses the public key to encrypt
- Three scoping modes: strict (name+namespace), namespace-wide, cluster-wide
- Controller auto-rotates keys every 30 days β old secrets remain decryptable
- Enables full GitOps β all cluster state, including secrets, lives in Git

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
