Kubernetes Secrets are base64-encoded, not encrypted. Committing them to Git is a security incident waiting to happen. Sealed Secrets solves this: encrypt secrets client-side, store the encrypted version in Git, and only the cluster can decrypt them.
How It Works
Developer ā kubeseal (encrypt) ā SealedSecret YAML ā Git ā Flux/ArgoCD ā Cluster
ā
Sealed Secrets Controller
ā
Decrypted Kubernetes SecretThe controller runs in the cluster and holds the private key. kubeseal uses the public key to encrypt. Only the cluster can decrypt.
Installation
# Install the controller
helm install sealed-secrets sealed-secrets/sealed-secrets \
--namespace kube-system
# Install the CLI
brew install kubesealMaster this topic with hands-on labs
Go beyond reading ā build real projects in sandboxed environments with expert video guidance.
Browse Courses āEncrypting Secrets
# Create a regular secret (don't apply it!)
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=s3cur3-p4ss \
--dry-run=client -o yaml > secret.yaml
# Encrypt it
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# Delete the unencrypted file
rm secret.yamlThe sealed secret looks like this:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
spec:
encryptedData:
username: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
password: AgCtr7BJ6FDKMblrSP0v4yGHsA3lMnQ+...This is safe to commit to Git. Without the cluster's private key, the values cannot be decrypted.
GitOps Integration
Store sealed secrets alongside your manifests:
deploy/
āāā production/
ā āāā deployment.yaml
ā āāā service.yaml
ā āāā sealed-secrets/
ā āāā db-credentials.yaml
ā āāā api-keys.yamlFlux or ArgoCD applies the SealedSecret. The controller decrypts it into a regular Secret. Your pods reference the Secret as normal:
env:
- name: DB_PASSWORD
valueFrom:
secretRef:
name: db-credentials
key: passwordScoping
Sealed Secrets supports three scopes:
Strict (default)
Sealed to a specific name and namespace. Cannot be renamed or moved:
kubeseal --scope strict --format yaml < secret.yamlNamespace-Wide
Can be renamed within the same namespace:
kubeseal --scope namespace-wide --format yaml < secret.yamlCluster-Wide
Can be used in any namespace with any name:
kubeseal --scope cluster-wide --format yaml < secret.yamlUse strict scope unless you have a specific reason not to.
Get weekly IT automation tips
Docker, Ansible, Terraform, MLOps ā curated insights delivered to your inbox. No spam.
Subscribe Free āKey Rotation
The controller generates a new key pair every 30 days by default. Old keys are retained for decryption. New secrets use the latest key.
# View current keys
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key
# Force key rotation
kubectl annotate secret -n kube-system \
-l sealedsecrets.bitnami.com/sealed-secrets-key \
sealedsecrets.bitnami.com/managed=trueTo re-encrypt secrets with the latest key:
# Fetch the new public key
kubeseal --fetch-cert > pub-cert.pem
# Re-encrypt
kubeseal --cert pub-cert.pem --format yaml < secret.yaml > sealed-secret.yamlBackup the Private Key
If you lose the private key, all sealed secrets become undecryptable:
# Backup the key
kubectl get secret -n kube-system \
-l sealedsecrets.bitnami.com/sealed-secrets-key \
-o yaml > sealed-secrets-key-backup.yaml
# Store this backup securely (NOT in Git)
# Use a password manager, vault, or encrypted storageAlternatives
| Tool | Approach | GitOps-friendly |
|---|---|---|
| Sealed Secrets | Encrypt at rest in Git | Yes |
| SOPS + age | Encrypt files with age/PGP keys | Yes |
| External Secrets Operator | Sync from Vault/AWS SM/GCP SM | Yes |
| Vault Agent Injector | Inject secrets at runtime | Partial |
Sealed Secrets is the simplest option for teams that want encrypted secrets in Git. External Secrets Operator is better if you already use a central secret manager.
---
Ready to go deeper? Master Kubernetes security with hands-on courses at CopyPasteLearn.
Ready to learn by doing?
Stop reading tutorials ā start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Sops Encrypted Secrets in Git
SOPS encrypts secret values in YAML, JSON, and dotenv files while keeping keys readable. Learn how to use SOPS with age, AWS KMS, or GCP KMS.
Ansible Vault Secrets Encryption
Encrypt secrets with Ansible Vault for secure automation. Cover file encryption, string-level vaulting, multi-password setups, and CI/CD pipeline integration.
Crossplane Infrastructure as Code
Crossplane lets you manage cloud infrastructure using Kubernetes custom resources. Learn how it works, how it compares to Terraform, and when to choose.
Securing Your OpenClaw Agent
Security guide for self-hosted OpenClaw agents ā API key management, network hardening, permission boundaries, and data protection.
SELinux for Apache and PHP-FPM
Configure Apache with PHP-FPM over TCP on RHEL with SELinux enforcing. Diagnose and fix name_connect denials using the correct SELinux boolean and audit tools.
SELinux Booleans Explained
SELinux booleans let you toggle common service behaviors without writing custom policy. Learn getsebool, setsebool, and the most useful httpd booleans.
Explore topics
Browse more articles on the topics covered here.