Learn how to encrypt and manage your Kubernetes secrets in Git using Mozilla SOPS with a PGP key, then let FluxCD decrypt them automatically on apply.
Prerequisites
A Git repository with your application code checked out.
Administrator-generated PGP keypair (public key committed in infrastructure/SOPS/).
FluxCD installed in your cluster.
gpg, git, wget, and kubectl available on your machine.
Table of Contents
Prepare the Repository
Import the Public PGP Key
Install SOPS
Encrypt the Secret with SOPS
Commit and Push
Configure FluxCD Decryption
Verify Decrypted Secret in Cluster
1. Prepare the Repository
Switch to your infrastructure branch and restore the plaintext secret for re-encryption.
cd bb-app-source/
git checkout infrastructure
Always back up existing sealed or encrypted secrets before modifying them.
Action Command Backup old Bitnami Sealed Secret mv database/secret-mysql-sealed.yaml database/secret-mysql-sealed.yaml.bakRestore plaintext secret manifest mv database/secret-mysql-backup.yaml database/secret-mysql.yaml
Verify the plaintext Secret at database/secret-mysql.yaml:
apiVersion : v1
kind : Secret
metadata :
name : secret-mysql
namespace : database
stringData :
password : mysql-password-0123456789
2. Import the Public PGP Key
On a fresh developer machine, confirm you have no existing public keys:
gpg --list-public-keys
# -> (no keys found)
Import the administrator’s public key:
gpg --import infrastructure/SOPS/dev-us-e1-k8s.pub
Validate the import and note the fingerprint (e.g., CE284BB236654E42A):
gpg --list-public-keys
# gpg: key CE284BB236654E42: public key "dev.us.e1.k8s (k8s) <[email protected] >" imported
You will use the PGP fingerprint with the sops CLI to encrypt your secret.
3. Install SOPS
Install the SOPS binary if it’s not already present:
cd ~
wget https://github.com/mozilla/sops/releases/download/v3.7.3/sops-v3.7.3.linux.amd64
chmod +x sops-v3.7.3.linux.amd64
sudo mv sops-v3.7.3.linux.amd64 /usr/local/bin/sops
Confirm the installation:
sops --version
# sops version 3.7.3
4. Encrypt the Secret with SOPS
Navigate to the directory containing your plaintext secret:
cd bb-app-source/database
cat secret-mysql.yaml
Encrypt only the data and stringData sections in place:
sops --encrypt \
--encrypted-regex= "^(data|stringData)$" \
--pgp CE284BB236654E42A \
--in-place secret-mysql.yaml
After encryption, secret-mysql.yaml will include an sops: block:
apiVersion : v1
kind : Secret
metadata :
name : secret-mysql
namespace : database
stringData :
password : ENC[AES256_GCM,data:...,iv:...]
sops :
pgp :
created_at : "2023-04-06T18:35:26Z"
enc : |
-----BEGIN PGP MESSAGE-----
hQGMAxQRIka4bFJ8AQv/...
-----END PGP MESSAGE-----
mac : ENC[AES256_GCM,data:...]
lastmodified : "2023-04-06T18:35:29Z"
Encryption Backends Supported by SOPS
Backend Description PGP Public-key encryption via GnuPG / GPG AWS KMS Key management using AWS Key Management Service GCP KMS Google Cloud Key Management Service integration Azure Key Vault Microsoft Azure Key Vault integration HashiCorp Vault Vault secret engine encryption
5. Commit and Push
Add the encrypted secret to your Git repository and push:
git add database/secret-mysql.yaml
git commit -m "chore: encrypt secret-mysql.yaml with SOPS"
git push origin infrastructure
FluxCD needs the private key stored in a Kubernetes Secret (e.g., sops-gpg) and decryption enabled in the Kustomization manifest.
Edit infrastructure/flux/kustomization-database.yaml:
apiVersion : kustomize.toolkit.fluxcd.io/v1beta2
kind : Kustomization
metadata :
name : infra-database-mysql
namespace : flux-system
spec :
interval : 10s
path : "./database"
prune : true
sourceRef :
kind : GitRepository
name : infra-source-git
targetNamespace : database
decryption :
provider : sops
secretRef :
name : sops-gpg
Commit and push the FluxCD configuration:
git add infrastructure/flux/kustomization-database.yaml
git commit -m "feat: enable SOPS decryption in Flux Kustomization"
git push origin infrastructure
For details, see FluxCD Kustomization Documentation .
7. Verify Decrypted Secret in Cluster
Trigger reconciliation and inspect the applied secret:
flux reconcile source git flux-system
flux reconcile kustomization infra-database-mysql
kubectl -n database get secret secret-mysql -o json \
| jq -r .data.password | base64 -d
# => mysql-password-0123456789
You should see the original plaintext password, confirming that FluxCD decrypted the secret before applying it.
Links and References