> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bitnami Sealed Secrets

> Explains using Bitnami Sealed Secrets and kubeseal to encrypt Kubernetes Secrets for safe GitOps storage and automated cluster decryption via a controller holding a private key.

In this lesson we examine how Bitnami Sealed Secrets enables secure, GitOps-friendly management of Kubernetes Secrets.

Kubernetes Secrets can be created with `kubectl` or a YAML manifest. A core GitOps principle is that every resource—including Secrets—should be stored declaratively in Git. That raises a key question: how do you keep sensitive (often Base64-encoded) data safe in a Git repository (public or private)?

There are multiple approaches (HashiCorp Vault, SOPS, Bitnami Sealed Secrets, etc.). This article focuses on Bitnami Sealed Secrets and explains how to create, store, and deploy encrypted Secret manifests that only the target cluster can decrypt.

## Overview

* The Bitnami Sealed Secrets controller is a Kubernetes controller installed into your cluster.
* The `kubeseal` client transforms a standard Kubernetes Secret manifest into a SealedSecret object that is safe to commit to Git because the secret data is encrypted.
* The controller running in the target cluster holds the private key and decrypts SealedSecret objects back into native Kubernetes Secrets.
* Only the controller (or anyone with access to its private key) can decrypt a SealedSecret. Even the author who created the SealedSecret cannot recover plaintext without the controller’s private key.
* You can install the controller with Helm, Kustomize, or via GitOps tools such as ArgoCD. The examples below show both Helm/GitOps options.

## How sealing and unsealing works

* On the client side you use the `kubeseal` utility to convert a native Secret YAML into a SealedSecret YAML.
* `kubeseal` uses asymmetric cryptography: the Sealed Secrets controller in the cluster holds the private key and `kubeseal` uses the controller’s public certificate to encrypt the Secret so that only the controller can decrypt it.
* By default `kubeseal` fetches the controller’s public certificate automatically over the Kubernetes API. You can also provide the certificate locally with `--cert` (useful when the cluster API is not reachable or for reproducible encryption).

## Quick reference: common commands

| Step                                     | Command / Example                                                                                                                                                                                              | Purpose                                                                           |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Create a local Secret manifest (dry-run) | `kubectl create secret generic mysql-password --from-literal=password='s1DdH@rtf' --dry-run=client -o yaml > mysql-password_k8s-secret.yaml`                                                                   | Export a standard Secret to YAML without applying it to the cluster.              |
| Create ArgoCD app (example)              | `argocd app create sealed-secrets \  --repo https://bitnami-labs.github.io/sealed-secrets \  --helm-chart sealed-secrets \  --revision 2.2.0 \  --dest-namespace kube-system \  --dest-server https://1.2.3.4` | Example: use ArgoCD to install the Sealed Secrets Helm chart into a cluster.      |
| Install kubeseal client                  | `wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/kubeseal-0.18.0-linux-amd64 -O kubeseal && \  sudo install -m 755 kubeseal /usr/local/bin/kubeseal`                             | Download and install the `kubeseal` binary locally.                               |
| Create SealedSecret YAML                 | `kubeseal -o yaml --scope cluster-wide --cert sealedSecret.crt < mysql-password_k8s-secret.yaml > mysql-password_sealed-secret.yaml`                                                                           | Encrypt the Secret YAML to produce a SealedSecret suitable for committing to Git. |

## Example workflow and commands (detailed)

1. Create a Kubernetes Secret manifest locally (dry-run) and export it to YAML:

```bash theme={null}
kubectl create secret generic mysql-password --from-literal=password='s1DdH@rtf' --dry-run=client -o yaml > mysql-password_k8s-secret.yaml
```

2. (Optional) Create an ArgoCD application to deploy the Sealed Secrets Helm chart into your cluster (example):

```bash theme={null}
argocd app create sealed-secrets \
  --repo https://bitnami-labs.github.io/sealed-secrets \
  --helm-chart sealed-secrets \
  --revision 2.2.0 \
  --dest-namespace kube-system \
  --dest-server https://1.2.3.4
# application 'sealed-secrets' created
```

3. Install the `kubeseal` client locally (example using a release binary):

```bash theme={null}
wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/kubeseal-0.18.0-linux-amd64 -O kubeseal && \
  sudo install -m 755 kubeseal /usr/local/bin/kubeseal
# kubeseal installed to /usr/local/bin/kubeseal
```

4. Create the SealedSecret YAML by running `kubeseal`. If `kubeseal` can reach the Sealed Secrets controller, it will fetch the controller’s public certificate automatically. You can also provide the certificate file using `--cert`:

```bash theme={null}
kubeseal -o yaml --scope cluster-wide --cert sealedSecret.crt < mysql-password_k8s-secret.yaml > mysql-password_sealed-secret.yaml
```

<Callout icon="lightbulb" color="#1CB2FE">
  If you omit `--cert`, `kubeseal` will try to fetch the controller's public certificate from the cluster. Use `--cert` when you cannot reach the cluster API from your local environment or when you want to ensure reproducible encryption using a specific certificate.
</Callout>

5. Commit the generated `mysql-password_sealed-secret.yaml` to your Git repository. Any GitOps operator (ArgoCD, Flux, etc.) can sync the manifest to the cluster.

6. At deploy time the Sealed Secrets controller running in the target cluster decrypts the SealedSecret and creates a native Kubernetes Secret in the cluster namespace. From the application pod’s perspective, this is a normal Secret and is consumed in the usual way (environment variables, volumes, etc.).

## Why this is secure

* SealedSecret objects are encrypted using the controller’s public key; only the controller’s private key (stored inside the cluster) can decrypt them.
* Storing SealedSecrets in Git is safe—even in public repositories—because the ciphertext cannot be converted back to plaintext without the controller’s private key.
* Application pods are unaware of the encryption step: they receive native Kubernetes Secrets at runtime exactly as they would with any conventional Secret.

## Best practices

* Keep the Sealed Secrets controller private key secure and limit access to the cluster control plane.
* Use `--cert` for reproducible encryption when working from CI/CD runners that cannot access the cluster API.
* Rotate the controller keys periodically and plan for re-sealing Secrets if keys are rotated or compromised.
* Use RBAC and network policies to limit who can create SealedSecrets and who can access Secrets in the cluster.

## Summary

Bitnami Sealed Secrets offers a simple, Git-friendly method for managing Kubernetes Secrets using asymmetric encryption. Use `kubeseal` to produce SealedSecret manifests, store those manifests in Git, and let your GitOps operator and the Sealed Secrets controller handle decryption and provisioning within the cluster.

## Links and references

* Bitnami Sealed Secrets GitHub: [https://github.com/bitnami-labs/sealed-secrets](https://github.com/bitnami-labs/sealed-secrets)
* kubeseal releases: [https://github.com/bitnami-labs/sealed-secrets/releases](https://github.com/bitnami-labs/sealed-secrets/releases)
* ArgoCD: [https://argo-cd.readthedocs.io/](https://argo-cd.readthedocs.io/)
* Kubernetes Secrets: [https://kubernetes.io/docs/concepts/configuration/secret/](https://kubernetes.io/docs/concepts/configuration/secret/)
* SOPS: [https://github.com/mozilla/sops](https://github.com/mozilla/sops)
* HashiCorp Vault: [https://www.vaultproject.io/](https://www.vaultproject.io/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gitops-certified-associate-cgoa/module/f1538ace-dc97-454d-b894-15bdd35bcb64/lesson/b5f617f3-f436-4f3d-87a0-e4971d42b0da" />
</CardGroup>
