SOPS vs. Age: Secrets verschlüsselt in Git speichern
Secrets in Git zu speichern gilt als Anti-Pattern — doch mit den richtigen Tools wird es zur sicheren Praxis. SOPS (Secrets OPerationS) und Age sind zwei Werkzeuge, die Secrets verschlüsseln, bevor sie ins Repository landen. Beide ergänzen sich häufig, adressieren aber unterschiedliche Probleme. Dieser Vergleich zeigt, wie sie funktionieren, wo sie sich unterscheiden — und wie man sie in GitOps-Workflows mit Kubernetes einsetzt.
Das Problem: Secrets in Git
Kubernetes-Manifeste, Helm-Values und GitOps-Repos enthalten regelmäßig sensible Daten: API-Keys, Datenbankpasswörter, TLS-Zertifikate. Wer diese unverschlüsselt committet, riskiert Datenlecks. Die typischen Lösungen:
- Sealed Secrets / External Secrets Operator: Secrets werden im Cluster verwaltet, nicht im Repo (vgl. External Secrets vs. Sealed Secrets)
- Vault: Zentrales Secrets-Management außerhalb von Git (vgl. Vault vs. Infisical)
- SOPS + Age/GPG: Secrets verschlüsselt in Git speichern — der Fokus dieses Artikels
Was ist Age?
Age (ausgesprochen wie das englische Wort "age") ist ein minimalistisches Verschlüsselungs-Tool, das 2021 von Filippo Valsorda (Google) veröffentlicht wurde. Das Designziel ist Einfachheit: keine Konfigurationsdateien, keine Schlüsselbunde, kein PGP-Overhead.
Age verschlüsselt beliebige Dateien:
# Schlüsselpaar erstellen
age-keygen -o ~/.config/age/key.txt
# Ausgabe: Public Key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
# Datei verschlüsseln
age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p secrets.yaml > secrets.yaml.age
# Datei entschlüsseln
age -d -i ~/.config/age/key.txt secrets.yaml.age > secrets.yaml
Age unterstützt:
- X25519 (Standard): Modernes Elliptic-Curve-Kryptographie
- SSH-Schlüssel: Bestehende SSH-Keys als Empfänger nutzen
- Passphrase-Verschlüsselung: Für interaktive Nutzung
- Plugin-System: Erweiterbar für Hardware-Security-Keys (YubiKey via
age-plugin-yubikey)
Age ist kein vollständiges Secrets-Management-System — es verschlüsselt Binärdateien und Textdateien, kennt aber keine Struktur. Hier kommt SOPS ins Spiel.
Was ist SOPS?
SOPS (Mozilla, 2017) ist ein CLI-Tool und eine Bibliothek, die strukturierte Dateien (YAML, JSON, ENV, INI) partiell verschlüsselt. Der Schlüssel: SOPS verschlüsselt nur die Werte, nicht die Schlüsselnamen. Das Ergebnis ist lesbar und diff-bar in Git:
# Originaldatei (secrets.yaml)
database:
password: "meinSicheresPasswort123!"
host: "db.example.com"
api_key: "sk-abc123xyz"
# Nach SOPS-Verschlüsselung mit Age
database:
password: ENC[AES256_GCM,data:xyz...,iv:...,tag:...,type:str]
host: db.example.com # NICHT verschlüsselt (kein Geheimnis)
api_key: ENC[AES256_GCM,data:abc...,iv:...,tag:...,type:str]
sops:
age:
- recipient: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
...
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-09-11T08:00:00Z"
version: 3.8.1
SOPS unterstützt als Verschlüsselungs-Backend:
- Age (empfohlen für neue Setups)
- GPG (historisch, komplexer)
- AWS KMS, Azure Key Vault, GCP KMS (für Cloud-Umgebungen)
- HashiCorp Vault Transit (für On-Premises-Enterprises)
SOPS + Age: Die optimale Kombination
SOPS und Age sind komplementär, nicht konkurrierend. Age ist der Verschlüsselungs-Algorithmus; SOPS ist der Orchestrator, der entscheidet, was verschlüsselt wird und wie Schlüssel verwaltet werden.
Konfiguration
# .sops.yaml (im Repo-Root)
creation_rules:
- path_regex: k8s/.*\.yaml$
age: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
- path_regex: .*/secrets/.*
age: >-
age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p,
age1team_member_2_public_key
# Secret erstellen und verschlüsseln
sops --encrypt secrets/db.yaml > secrets/db.enc.yaml
# Secret bearbeiten (öffnet Editor, speichert verschlüsselt)
sops secrets/db.enc.yaml
# In CI/CD entschlüsseln
export SOPS_AGE_KEY_FILE=~/.config/age/key.txt
sops --decrypt secrets/db.enc.yaml | kubectl apply -f -
Multi-Empfänger: Teamzugang
Ein wichtiger Vorteil von SOPS: Eine Datei kann für mehrere Schlüssel verschlüsselt werden. Jedes Teammitglied und jede CI/CD-Pipeline erhält eigene Age-Schlüssel — niemand teilt denselben privaten Schlüssel.
# Neuen Empfänger hinzufügen
sops --rotate --add-age age1NEW_TEAM_MEMBER secrets/db.enc.yaml
GitOps-Integration: Argo CD und Flux
Argo CD mit SOPS (via argocd-vault-plugin)
# Application mit SOPS-Entschlüsselung
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
annotations:
argocd.argoproj.io/hook: PreSync
spec:
source:
plugin:
name: argocd-vault-plugin
Moderner Ansatz: argocd-cmp-plugin mit SOPS direkt als Config Management Plugin:
# argocd-cm ConfigMap
configManagementPlugins: |
- name: sops
generate:
command: ["sh", "-c"]
args: ["sops -d $ARGOCD_APP_SOURCE_PATH/secrets.yaml | kubectl apply -f -"]
Flux CD mit SOPS (nativ unterstützt)
Flux hat native SOPS-Unterstützung seit v2 — kein Plugin nötig:
# flux-system/gotk-sync.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
spec:
decryption:
provider: sops
secretRef:
name: sops-age # Secret mit dem privaten Age-Schlüssel
sourceRef:
kind: GitRepository
name: my-repo
# Age-Schlüssel als Kubernetes-Secret für Flux
kubectl create secret generic sops-age --namespace=flux-system --from-file=age.agekey=~/.config/age/key.txt
SOPS vs. Age: Feature-Vergleich
| Feature | Age (direkt) | SOPS + Age |
|---|---|---|
| Struktur-bewusst | Nein (alles oder nichts) | Ja (nur Values) |
| Git-Diff-freundlich | Nein (ganze Datei binär) | Ja (Schlüssel sichtbar) |
| Multi-Empfänger | Via Age-Optionen | Native, konfigurierbar |
| KMS-Integration | Nein | Ja (AWS/Azure/GCP) |
| Rotation | Manuell | sops --rotate |
| Kubernetes-Native | Via kubectl | Via Flux/Argo-Plugin |
| Lernkurve | Minimal | Niedrig-mittel |
Vergleich mit alternativen Ansätzen
| Ansatz | Vorteile | Nachteile |
|---|---|---|
| SOPS + Age | Git-nativ, diff-bar, offline | Key-Distribution manuell |
| Sealed Secrets | Kubernetes-nativ, einfach | Nur für K8s, kein GitOps-Editor |
| External Secrets | Vault/AWS-Integration | Externe Abhängigkeit |
| GPG statt Age | Weit verbreitet | Komplexer, veraltetes UX |
| Vault + KV | Enterprise-ready | Mehr Infrastruktur |
Wann SOPS + Age, wann Alternativen?
SOPS + Age ist optimal wenn:
- Secrets verschlüsselt im Git-Repository liegen sollen
- GitOps mit Flux oder Argo CD genutzt wird
- Kein KMS-Dienst vorhanden ist (kein AWS/Azure/GCP)
- Mehrere Teammitglieder Zugriff benötigen (Multi-Empfänger)
- Diff-Sichtbarkeit in Pull-Requests wichtig ist
Alternativen bevorzugen wenn:
- AWS/Azure/GCP im Einsatz: SOPS + KMS direkt (ohne Age)
- Einfachster K8s-Setup: Sealed Secrets
- Enterprise On-Premises: Vault Transit + External Secrets
Fazit
Age allein reicht für einfache Datei-Verschlüsselung. Wer YAML-/JSON-Dateien strukturiert verschlüsseln und mit GitOps-Tools wie Argo CD oder Flux nutzen möchte, braucht SOPS als Orchestrator über Age als Backend. Die Kombination SOPS + Age ist 2026 der Standard für GitOps-konforme Secret-Verwaltung ohne Cloud-KMS-Abhängigkeit.
Für Kubernetes-Umgebungen mit hohen Compliance-Anforderungen lohnt der Blick auf External Secrets Operator vs. Sealed Secrets und Vault vs. Infisical als ergänzende oder alternative Lösungen.
Weiterführende Artikel
- External Secrets Operator vs. Sealed Secrets: Kubernetes Secrets Management im Vergleich
- Vault vs. Infisical: Secrets Management für Self-Hosting und Kubernetes im Vergleich
- Cert-Manager vs. acme.sh: TLS-Zertifikate für Kubernetes automatisieren
- ArgoCD vs. Flux CD: GitOps-Tools für Kubernetes im Vergleich
- Crossplane vs. Terraform: Infrastructure-as-Code für Kubernetes im Vergleich