Learn how to create and manage encrypted secrets with this SOPS GitOps setup.
Copy and customize from the provided example:
# Copy from example
cp examples/basic-secret.yaml my-app-secret.yaml
# Edit with your values
vim my-app-secret.yamlKey requirement: Add the encryption annotation:
annotations:
def.ms/sops-encrypt: "true" # ⚠️ Required for encryption!# Add and commit - encryption happens automatically
git add my-app-secret.yaml
git commit -m "Add encrypted database secret"
git pushWhat happens: Git automatically encrypts secrets with the annotation, stores encrypted SopsSecret in Git, while your working directory shows the readable Secret.
Use the provided examples as templates:
# Basic credentials - see examples/basic-secret.yaml
cp examples/basic-secret.yaml my-app-credentials.yaml# Container registry auth - see examples/docker-config.yaml
cp examples/docker-config.yaml my-registry-secret.yaml# TLS certs and keys - see examples/tls-secret.yaml
cp examples/tls-secret.yaml my-tls-secret.yamlUse stringData for plain text values (recommended):
stringData:
password: "myplaintextpassword"
config: |
server:
host: api.example.comUse data for base64-encoded values:
data:
encoded-value: dGVzdA== # base64: "test"See examples/mixed-fields.yaml for both field types in one secret.
# View decrypted secret (working directory)
cat my-app-secret.yaml
# View encrypted secret (stored in Git)
git show HEAD:my-app-secret.yaml# Edit the secret normally
vim my-app-secret.yaml
# Commit changes - re-encryption happens automatically
git add my-app-secret.yaml
git commit -m "Update database password"Simply add new fields to your secret file:
stringData:
username: "myuser"
password: "mypass"
new-api-key: "token-12345" # New fieldOnly secrets with the annotation are encrypted:
Encrypted secrets:
annotations:
def.ms/sops-encrypt: "true" # ✅ Will be encryptedUnencrypted secrets:
annotations:
description: "Public configuration" # ❌ No encryption annotationSee examples/unencrypted-secret.yaml for an example of unencrypted secrets.
Use YAML's | syntax for multi-line content:
stringData:
app-config.yaml: |
server:
host: "api.example.com"
port: 8443
database:
host: "db.example.com"
port: 5432
config.json: |
{
"api": {
"key": "secret-api-key",
"endpoint": "https://api.example.com"
}
}For certificates and scripts, see the examples in examples/ directory.
- Use descriptive names:
postgres-primary-credentialsnotsecret1 - Add helpful annotations: Include description, owner, rotation policy
- Use appropriate namespaces: Environment-specific namespaces
- Group related secrets: Multiple related values in one secret
- Add labels: For organization and selection
Example with good practices:
metadata:
name: postgres-primary-credentials
namespace: production
labels:
app: my-application
component: database
annotations:
def.ms/sops-encrypt: "true"
description: "PostgreSQL primary database credentials"
owner: "platform-team"
stringData:
postgres-username: "app_user"
postgres-password: "secret123"
postgres-host: "postgres.internal.com"Secret not encrypting?
# Check for encryption annotation
grep "def.ms/sops-encrypt" my-secret.yaml
# Verify Git filter is configured
git config filter.sops.cleanTest filters manually:
# Test encryption
cat my-secret.yaml | ./sops-clean.py
# Test decryption
git show HEAD:my-secret.yaml | ./sops-smudge.pyRun full test suite:
./run-e2e-tests.sh localYour encrypted secrets work with GitOps tools:
- ArgoCD/Flux syncs encrypted SopsSecret from Git
- SOPS Secrets Operator decrypts and creates target Secret
- Your application uses the decrypted Secret
Requires SOPS Secrets Operator in your cluster.