Sealed Secrets¶
No plaintext secret is ever committed to Git. Secrets are encrypted with Sealed Secrets before they go into a repo; only the matching in-cluster controller holds the private key that can decrypt them, so the sealed value is safe to store in a public repository.
One controller per layer¶
Each layer runs its own controller, so one layer's key can never decrypt another layer's secrets:
| Controller | Namespace | Seals for |
|---|---|---|
sealed-secrets-platform |
platform-shared |
platform-layer namespaces |
sealed-secrets-addons |
addons-shared |
addons-layer namespaces |
sealed-secrets-opendesk |
opendesk-addons |
openDesk namespaces |
Sealing a value¶
Pick the controller for the layer whose namespace you're sealing into, and use strict scope โ the ciphertext is bound to that exact namespace and secret name:
printf '%s' 'the-secret-value' | kubeseal --raw \
--namespace <target-namespace> --name <secret-name> --scope strict \
--controller-name <controller> --controller-namespace <controller-namespace>
Paste the resulting ciphertext into a SealedSecret manifest under the right key. Commit โ
ArgoCD applies the SealedSecret, and the controller decrypts it into a real Secret in the
cluster.
Rules of the road¶
--scope strict: the sealed value only works for that namespace + secret name. Renaming or moving it means re-sealing.- Run the pipe locally โ the plaintext is piped straight into
kubesealand never leaves your workstation or lands in a file. - The controller's private key is the crown jewel. It's backed up out-of-band, never in Git. Restore it and every existing
SealedSecretstill decrypts; lose it and they must all be re-sealed.
See also: Architecture ยท Operations.