Storing configuration files in Git is a cornerstone of infrastructure-as-code and self-hosted server management. But configuration files often contain passwords, API keys, TLS certificates, and database credentials. Committing these in plaintext is a security risk that can lead to data breaches, especially in shared repositories.
The solution is encrypting sensitive files before they enter version control. Three open-source tools dominate this space: Mozilla SOPS, git-crypt, and age. Each takes a fundamentally different approach to the problem, and choosing the right one depends on your team size, infrastructure complexity, and threat model.
In this guide, we compare all three tools side-by-side with real configuration examples, so you can pick the best encryption workflow for your self-hosted infrastructure.
Why Encrypt Secrets in Git?
Version control systems like Git keep every version of every file forever. Once a plaintext password is committed — even briefly — it exists in the repository history permanently. Removing it requires rewriting history with git filter-branch or git filter-repo, which is disruptive and error-prone.
Encrypting sensitive files before they are committed solves this problem at the source:
- Prevents accidental exposure — encrypted files are useless without the decryption key
- Enables GitOps workflows — encrypted secrets can be stored alongside application configuration in the same repository
- Supports team collaboration — multiple people can encrypt and decrypt files without sharing a single master password
- Satisfies compliance requirements — many security standards require secrets to be encrypted at rest
The Threat Model
The tools covered here protect against repository compromise — if someone gains read access to your Git repository (through a leaked token, compromised collaborator account, or backup exposure), encrypted files remain unreadable. They do not protect against:
- Compromised decryption keys on a developer’s machine
- Malicious CI/CD pipelines that have decryption access
- Social engineering attacks to obtain key material
Choose your encryption tool accordingly and implement proper key management alongside file encryption.
Mozilla SOPS
Mozilla SOPS (Secrets OPerationS) is a flexible, widely-adopted tool for managing encrypted secrets. It supports YAML, JSON, ENV, INI, and binary file formats, and integrates with multiple key management backends including AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault, and PGP/GPG keys.
| Metric | Value |
|---|---|
| Repository | mozilla/sops |
| Stars | 21,571 |
| Language | Go |
| Last Active | April 2026 |
| License | MPL-2.0 |
Key Features
- Partial encryption — SOPS encrypts only the values in YAML/JSON files, leaving keys in plaintext. This means you can still diff, review, and merge encrypted files without decrypting them.
- Multiple key backends — Supports AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault, PGP, and age keys simultaneously.
- Age integration — Native support for age keys as a lightweight alternative to PGP.
- Editor integration — Seamless editing via
sops <file>which decrypts to a temp file, opens your editor, and re-encrypts on save. - Git hooks — Works with pre-commit hooks to auto-encrypt files before commit.
Installation
| |
Configuration and Usage
Create a .sops.yaml configuration file at the root of your repository:
| |
Encrypt a file:
| |
Example encrypted output (note how keys remain readable):
| |
CI/CD Integration with Docker Compose
Here’s a Docker Compose setup for running SOPS in a CI/CD pipeline:
| |
git-crypt
git-crypt is a Git extension that provides transparent file encryption and decryption using Git’s built-in clean/smudge filter mechanism. Files are automatically encrypted on commit and decrypted on checkout, making the encryption completely transparent to your normal Git workflow.
| Metric | Value |
|---|---|
| Repository | AGWA/git-crypt |
| Stars | 9,601 |
| Language | C++ |
| Last Active | September 2025 |
| License | GPL-2.0 |
Key Features
- Transparent encryption — Files are automatically encrypted when committed and decrypted when checked out. No extra commands needed in your daily workflow.
- GPG-based key sharing — Uses GPG public keys to grant decryption access to specific users.
- File-level granularity — Specify which files or directories to encrypt via a
.gitattributesfile. - Hybrid mode — Can store encrypted versions of files in the repository while keeping plaintext versions in the working directory.
Installation
| |
Configuration and Usage
Initialize git-crypt in your repository:
| |
Configure which files to encrypt via .gitattributes:
| |
Add collaborators with their GPG public keys:
| |
Commit your files normally — git-crypt handles encryption transparently:
| |
Exporting the Key for CI/CD
For CI/CD pipelines, export the symmetric key and store it as a CI secret:
| |
Docker Compose example for a CI pipeline:
| |
age
age is a simple, modern encryption tool designed by Filippo Valsorda (a Go core team member and cryptography expert). Unlike SOPS and git-crypt, age is not specifically a Git tool — it’s a general-purpose file encryption utility that happens to work excellently for encrypting secrets before storing them in version control.
| Metric | Value |
|---|---|
| Repository | FiloSottile/age |
| Stars | 22,071 |
| Language | Go |
| Last Active | March 2026 |
| License | BSD-3-Clause |
Key Features
- Minimal design — No config files, no keyring daemons, no complex setup. Just encrypt and decrypt with a key file.
- X25519 encryption — Uses modern, audited cryptography (X25519 key exchange + ChaCha20-Poly1305).
- Small keys — Public keys are short, human-readable strings starting with
age1. Secret keys fit in a single small file. - SSH key support — Can encrypt files using existing SSH public keys (
age -R ~/.ssh/id_ed25519.pub). - Password-based encryption — Supports passphrase encryption with
--passphrasefor simple single-user scenarios. - Multi-recipient — A single file can be encrypted for multiple recipients (keys).
Installation
| |
Configuration and Usage
Generate a key pair:
| |
Encrypt and decrypt files:
| |
Encrypting in a Git workflow requires a pre-commit hook to encrypt before committing and a post-checkout hook to decrypt. Here’s a practical .gitattributes-inspired workflow using a wrapper script:
| |
Docker Compose Setup for age
| |
Head-to-Head Comparison
| Feature | Mozilla SOPS | git-crypt | age |
|---|---|---|---|
| Primary Focus | Secrets management in YAML/JSON | Transparent Git encryption | General-purpose file encryption |
| Encryption Scope | Values only (keys remain visible) | Entire file | Entire file |
| Key Management | AWS KMS, GCP KMS, Azure KV, Vault, PGP, age | GPG | age keys, SSH keys, passphrases |
| Partial Editing | Yes — edit encrypted values directly | No — must decrypt full file | No — must decrypt full file |
| Git Integration | Manual (CLI commands) | Automatic (clean/smudge filters) | Manual (requires hooks) |
| File Formats | YAML, JSON, ENV, INI, binary | Any file type | Any file type |
| Multi-recipient | Yes (per backend) | Yes (via GPG) | Yes (native) |
| CI/CD Friendly | Excellent | Good (requires key export) | Excellent |
| Setup Complexity | Medium | Low-Medium | Low |
| Learning Curve | Moderate | Low | Very low |
| Star Count | 21,571 | 9,601 | 22,071 |
| Active Development | Yes (April 2026) | No (September 2025) | Yes (March 2026) |
| License | MPL-2.0 | GPL-2.0 | BSD-3-Clause |
Choosing the Right Tool
Choose Mozilla SOPS When:
- You manage multiple environments (dev, staging, production) with different access controls
- You need partial encryption — want to keep YAML keys visible for code review while encrypting values
- Your team already uses cloud KMS providers (AWS KMS, GCP KMS, Azure Key Vault)
- You want audit trails through cloud provider KMS logging
- You work primarily with YAML/JSON configuration files
SOPS is the industry standard for Kubernetes and cloud-native environments. It pairs well with tools like Kubernetes secrets management solutions when you need to deploy encrypted secrets to clusters.
Choose git-crypt When:
- You want zero-friction Git workflow — encrypt on commit, decrypt on checkout, no extra commands
- Your team already uses GPG for code signing and email encryption
- You need per-file encryption granularity via
.gitattributes - You want to encrypt any file type (binary files, certificates, keystores)
git-crypt is ideal for small teams where GPG is already part of the workflow. However, note that development has slowed — the last significant commit was in September 2025.
Choose age When:
- You want the simplest possible setup — generate a key, encrypt, done
- You prefer modern cryptography without PGP’s complexity
- You need to encrypt ad-hoc files outside of a formal secrets management system
- You want a permissive license (BSD-3-Clause) for commercial use
- You already use SSH keys and want to leverage them for encryption
age is the most popular of the three by GitHub stars and has the lowest barrier to entry. It works well alongside encrypted backup solutions for protecting configuration backups.
The Hybrid Approach
Many teams combine these tools:
- age for ad-hoc file encryption and simple single-user scenarios
- SOPS for structured YAML/JSON secrets with cloud KMS integration
- git-crypt for transparent encryption of binary assets (certificates, keystores) in Git
For example, you might use SOPS for Kubernetes manifest files, age for encrypting individual configuration files shared between team members, and git-crypt for encrypting TLS certificates stored in the repository.
Security Best Practices
Regardless of which tool you choose, follow these security practices:
Key Management
| |
Access Control
- Rotate keys regularly — especially when team members leave
- Use separate keys per environment — a compromised dev key should not expose production secrets
- Audit access — track who has decryption keys for each environment
Pre-Commit Hooks
Add a pre-commit hook to prevent accidentally committing unencrypted secrets:
| |
Migration Paths
From Plaintext to SOPS
| |
From git-crypt to age
| |
FAQ
Which tool is best for encrypting secrets in Git?
For most self-hosted infrastructure teams, Mozilla SOPS with age keys provides the best balance of features and simplicity. It encrypts only the values (keeping keys visible for diffs), supports multiple key backends, and integrates seamlessly with YAML/JSON configuration files. For simpler single-user setups, age alone is the easiest option.
Can I use age without Git hooks?
Yes. age is a standalone file encryption tool. You can manually encrypt files with age -r <key> -o file.yaml.age file.yaml and commit the .age files to Git. However, without hooks, you’ll need to remember to encrypt before committing and decrypt after checking out. For a more seamless workflow, combine age with pre-commit/post-checkout Git hooks or use SOPS, which has built-in edit workflows.
Is git-crypt still actively maintained?
As of early 2026, git-crypt’s development has slowed significantly. The last major update was in September 2025. The tool is stable and works well for its intended purpose, but teams concerned about long-term maintenance may prefer SOPS or age, both of which have active development communities.
How do I rotate encryption keys?
With SOPS: update your .sops.yaml with the new public key, then run sops updatekeys <file> for each encrypted file. With age: encrypt a new copy of each file with the new recipient key using age -r <new-key> -o new-file.age old-file.age. With git-crypt: generate a new GPG key and run git-crypt add-gpg-user <new-fingerprint>, then remove the old user with git-crypt remove-gpg-user <old-fingerprint>.
Can I use these tools with CI/CD pipelines?
All three tools work with CI/CD. For SOPS, pass the age key file or cloud KMS credentials as CI secrets. For git-crypt, export the symmetric key with git-crypt export-key and store it as a CI secret, then unlock with git-crypt unlock <key> in the pipeline. For age, store the key file as a CI secret and use age -d -i key.txt to decrypt during builds.
What happens if I lose my decryption key?
You permanently lose access to the encrypted files. There is no backdoor or recovery mechanism in any of these tools. This is by design — it’s what makes the encryption secure. Always back up your keys to multiple secure locations (hardware tokens, password managers, offline storage) and consider using multi-recipient encryption so no single key is a single point of failure.
Does encrypting secrets in Git replace a secrets manager?
No. File encryption in Git solves the problem of storing secrets in version control, but it doesn’t address runtime secret delivery, rotation, auditing, or access control. For production systems, consider combining Git-based encryption with a dedicated secrets management solution like HashiCorp Vault or Infisical for runtime secret distribution.