Sealed secrets
Encrypt secrets with kubeseal, commit them safely to git, and reference them from deployments.
Bitnami Sealed Secrets lets you commit encrypted secrets to git. kdef gives them a first-class block: no YAML gymnastics, no wrapping kubeseal in shell scripts.
Prerequisites
kubesealinstalled locally- Sealed-secrets controller running in the cluster
# macOS
brew install kubeseal
# Linux
wget https://github.com/bitnami-labs/sealed-secrets/releases/latest/download/kubeseal-linux-amd64
chmod +x kubeseal-linux-amd64 && sudo mv kubeseal-linux-amd64 /usr/local/bin/kubeseal
Seal a single value
kdef seal --secret db-credentials --namespace production --key DATABASE_URL \
--value "postgres://api:hunter2@db:5432/api"
Output (the ciphertext on stdout, the usage hint on stderr):
AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq...
Usage in .kdef:
sealedsecret "db-credentials" {
namespace = "production"
data = {
DATABASE_URL = "AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq..."
}
}
Or pipe from stdin so the plaintext never touches your shell history:
echo -n "hunter2" | kdef seal --secret db-credentials --namespace production --key PASSWORD
Seal an existing Secret
If you already have a live Kubernetes Secret, seal-secret turns the whole thing into a ready-to-commit block:
kdef seal-secret --name db-credentials --namespace production
Output:
sealedsecret "db-credentials" {
namespace = "production"
data = {
DATABASE_URL = "AgBy3i4OJSWK+PiTySYZZA9rO..."
READONLY_URL = "AgBz2j5PKTXL+QjUzTZaaB0sP..."
}
}
Drop that into secrets.kdef and commit it.
Use it in a deployment
The secret() function works the same for plain secret blocks and sealedsecret blocks: you reference by name, not by storage mechanism.
# secrets.kdef
sealedsecret "db-credentials" {
namespace = "production"
data = {
DATABASE_URL = "AgBy3i4OJSWK+PiTySYZZA9rO..."
}
}
# api.kdef
deployment "api" {
namespace = "production"
container "api" {
image = image("api")
env {
DATABASE_URL = secret("db-credentials", "DATABASE_URL")
}
}
}
At deploy time the controller decrypts the SealedSecret into a regular Secret, and the pod reads from it via valueFrom.secretKeyRef.
Rotating a value
To rotate a key, re-seal with the new value and replace the ciphertext:
kdef seal --secret db-credentials --namespace production --key DATABASE_URL \
--value "postgres://api:new-password@db:5432/api"
Paste the new ciphertext into secrets.kdef, commit, and let your GitOps tool apply it.
Tips
- Different clusters have different sealing keys. A SealedSecret encrypted for staging won't decrypt in production. Re-seal per target cluster.
- The ciphertext is also bound to the Secret's name and namespace.
--namespacedefaults todefault, so pass the namespace yoursealedsecretblock lives in. - If you run
sealed-secretsin a non-default namespace or with a non-default controller name, pass--controller-namespaceand--controller-nametokdef seal(andkdef seal-secret). - For local development you usually want plain
secretblocks: they don't needkubesealand render as normalv1/Secretmanifests.