This guide walks you through setting up SOPS (Secrets OPerationS) for secure secret management in your NixOS dotfiles.
- Age or GPG key for encryption
- SOPS installed (
nix developincludes it)
# Generate age key
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
# Show public key (copy this for .sops.yaml)
age-keygen -y ~/.config/sops/age/keys.txtEdit .sops.yaml and add your age public key:
keys:
- &user age1your_age_key_here_from_previous_step
creation_rules:
- path_regex: secrets\.yaml$
key_groups:
- age:
- *user# Create/edit secrets file
sops secrets.yamlAdd your secrets in YAML format (replace example values with your actual information):
user:
name: "yourusername"
email: "your@email.com"
realName: "Your Real Name"
githubUsername: "yourghusername"
domains:
primary: "your-domain.com"
vpn: "vpn.your-domain.com"
internal: "internal.your-domain.com"The secrets are automatically available in your system configurations through:
config.sops.secrets."user/name".path # Contains your username
config.sops.secrets."user/email".path # Contains your email
config.sops.secrets."user/realName".path # Contains your real name
config.sops.secrets."user/githubUsername".path # Contains your GitHub username
config.sops.secrets."domains/primary".path # Contains your primary domain
config.sops.secrets."domains/vpn".path # Contains your VPN domain
config.sops.secrets."domains/internal".path # Contains your internal domainCritical: Backup your age key file. Without it, you cannot decrypt your secrets!
# Backup to secure location
cp ~/.config/sops/age/keys.txt /path/to/secure/backup/- Generate new age key
- Update
.sops.yamlwith new public key - Re-encrypt secrets:
sops updatekeys secrets.yaml - Deploy to systems
- Remove old key from
.sops.yaml
- Get their age public key
- Add to
.sops.yaml:
keys:
- &user1 age1your_key
- &user2 age1their_key
creation_rules:
- path_regex: secrets\.yaml$
key_groups:
- age:
- *user1
- *user2- Re-encrypt:
sops updatekeys secrets.yaml
- Age keys:
chmod 600 ~/.config/sops/age/keys.txt - SOPS config:
chmod 644 .sops.yaml - Encrypted secrets:
chmod 644 secrets.yaml(safe since encrypted)
- Store age keys in secure, backed-up location
- Consider hardware security keys for critical environments
- Never commit unencrypted age keys to git
- Use separate keys for different environments (dev/staging/prod)
- Regularly audit who has access to which secrets
- Rotate keys periodically
- Verify age key exists:
ls ~/.config/sops/age/keys.txt - Check
.sops.yamlhas correct public key - Ensure SOPS_AGE_KEY_FILE environment variable points to key file
- Verify your public key is in the encrypted file's key list
- Check file permissions on age key
- Try decrypting manually:
sops -d secrets.yaml
- Ensure SOPS module is imported in host configurations
- Verify secret paths match what's defined in
modules/sops.nix - Check that age key exists on target system at
/var/lib/sops-nix/key.txt
If you have an existing secrets.nix file:
- Copy values to SOPS format in
secrets.yaml - Test with
sops -d secrets.yaml - Update configurations to use SOPS paths
- Remove old
secrets.nixfile - Deploy and verify
# .sops.yaml
creation_rules:
- path_regex: secrets/dev\.yaml$
key_groups:
- age: [*dev_key]
- path_regex: secrets/prod\.yaml$
key_groups:
- age: [*prod_key]Use SOPS templates for complex configurations:
sops.templates."config.json".content = ''
{
"api_key": "${config.sops.placeholder."api/key"}",
"database_url": "${config.sops.placeholder."db/url"}"
}
'';For more advanced features, see the sops-nix documentation.