SOPS (Secrets OPerationS) Management
This documentation covers the SOPS (Secrets OPerationS) integration used in this NixOS/Darwin configuration for secure secrets management.
Overview
SOPS is a tool for managing secrets (passwords, keys, certificates, etc.) in a secure, encrypted format. This configuration uses SOPS with age encryption to manage sensitive data across all systems.
Key Features
- Age Encryption: Uses modern age encryption for security
- Cross-Platform: Works on both NixOS and Darwin systems
- Git-Safe: Encrypted secrets can be safely committed to version control
- Flexible: Supports multiple encryption keys and formats
Architecture
Encryption Keys
The system uses age keys for encryption with platform-specific locations:
Darwin (macOS):
- Location:
/Users/roelc/.config/sops/age/keys.txt - Format: Standard age private key format
- Generation: Automatically generated when missing
Linux (NixOS):
- Location:
/home/roelc/.config/sops/age/keys.txt - Format: Standard age private key format
- Generation: Automatically generated when missing
SSH Keys (Linux Only)
On NixOS systems, SSH host keys provide additional security:
- Location:
/etc/ssh/ssh_host_ed25519_key(or persistence path if enabled) - Persistence Path:
${config.dc-tec.persistence.dataPrefix}/etc/ssh/ssh_host_ed25519_key - Purpose: Additional encryption layer for system-level secrets
- Condition: Only used when
config.dc-tec.isLinuxis true
Secrets Configuration
Default Settings
sops = {
defaultSopsFile = ../../../secrets/secrets.yaml;
defaultSopsFormat = "yaml";
age = {
keyFile =
if config.dc-tec.isDarwin then
"/Users/${config.dc-tec.user.name}/.config/sops/age/keys.txt"
else
"/home/${config.dc-tec.user.name}/.config/sops/age/keys.txt";
sshKeyPaths = lib.optionals config.dc-tec.isLinux [
(if config.dc-tec.persistence.enable then
"${config.dc-tec.persistence.dataPrefix}/etc/ssh/ssh_host_ed25519_key"
else
"/etc/ssh/ssh_host_ed25519_key")
];
generateKey = true;
};
};
Managed Secrets
User Management Secrets
users/roelc: User password hash (Linux only,neededForUsers = true)users/root: Root password hash (Linux only,neededForUsers = true)
SSH Access Secrets
authorized_keys/roelc: SSH public keys deployed to/home/roelc/.ssh/authorized_keys(Linux) or/Users/roelc/.ssh/authorized_keys(Darwin)authorized_keys/root: SSH public keys deployed to/root/.ssh/authorized_keys(Linux only)
GPG Key Management
gpg/private_key: GPG private key deployed to~/.gnupg/private-key.asc(mode 0600)gpg/public_key: GPG public key deployed to~/.gnupg/public-key.asc(mode 0644)gpg/trust_db: GPG trust database deployed to~/.gnupg/trust-db.txt(mode 0600)
Network Secrets
wireless: Wireless network credentials (Linux only)
Platform-Specific Configuration
NixOS (Linux):
- User password hashes for system login
- Wireless network credentials
- Root SSH access keys
- Full GPG key management
Darwin (macOS):
- User SSH keys only
- GPG key management
- No wireless or user password management
Initial Setup
1. Generate Age Keys
Age keys are automatically generated by the NixOS/Darwin configuration when missing. The system will create them at the appropriate location based on your platform.
For manual generation (if needed):
# Darwin (macOS)
mkdir -p /Users/roelc/.config/sops/age
age-keygen -o /Users/roelc/.config/sops/age/keys.txt
# Linux (NixOS)
mkdir -p /home/roelc/.config/sops/age
age-keygen -o /home/roelc/.config/sops/age/keys.txt
2. Get Public Key
Extract your public key for adding to the repository's .sops.yaml:
# Darwin
age-keygen -y /Users/roelc/.config/sops/age/keys.txt
# Linux
age-keygen -y /home/roelc/.config/sops/age/keys.txt
3. Add to Repository Configuration
Add your public key to the .sops.yaml file in the repository root:
keys:
- &roelc_key age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
creation_rules:
- path_regex: secrets/secrets.yaml$
key_groups:
- age:
- *roelc_key
The secrets are stored in secrets/secrets.yaml and automatically referenced by the configuration.
Managing Secrets
Adding New Secrets
-
Edit the secrets file:
sops secrets/secrets.yaml -
Add your secret following the existing structure:
# Add to existing categories or create new ones
new_category:
secret_name: "secret_value" -
Configure in the sops.nix module (if not already handled):
sops.secrets."new_category/secret_name" = {
path = "/path/to/secret/file";
owner = config.dc-tec.user.name;
mode = "0600";
};
Updating Existing Secrets
# Edit existing secrets
sops secrets/secrets.yaml
# Re-encrypt for new keys (when adding new machines)
sops updatekeys secrets/secrets.yaml
Viewing Secrets
# View all decrypted secrets (local only)
sops -d secrets/secrets.yaml
# View specific secret categories
sops -d --extract '["users"]' secrets/secrets.yaml
sops -d --extract '["authorized_keys"]' secrets/secrets.yaml
sops -d --extract '["gpg"]' secrets/secrets.yaml
Common Workflows
Updating User Passwords
-
Generate password hash:
mkpasswd -m sha-512 "new_password" -
Update in secrets:
sops secrets/secrets.yamlusers:
roelc: "$6$new_hashed_password..."
root: "$6$new_hashed_password..." -
Apply changes:
# NixOS
sudo nixos-rebuild switch --flake .#hostname
Managing SSH Access
-
Update SSH public keys in secrets:
sops secrets/secrets.yamlauthorized_keys:
roelc: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... roelc@newhost"
root: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... roelc@newhost" -
Keys are automatically deployed to:
/home/roelc/.ssh/authorized_keys(Linux/Darwin)/Users/roelc/.ssh/authorized_keys(Darwin)/root/.ssh/authorized_keys(Linux only)
Updating Wireless Credentials
-
Update wireless password (NixOS only):
sops secrets/secrets.yamlwireless: "new_wifi_password" -
Apply changes:
sudo nixos-rebuild switch --flake .#hostname
Managing GPG Keys
-
Export your current GPG keys:
# Export private key
gpg --export-secret-keys --armor YOUR_KEY_ID > private-key.asc
# Export public key
gpg --export --armor YOUR_KEY_ID > public-key.asc
# Export trust database
gpg --export-ownertrust > trust-db.txt -
Add to secrets:
sops secrets/secrets.yamlgpg:
private_key: |
-----BEGIN PGP PRIVATE KEY BLOCK-----
[paste private key content]
-----END PGP PRIVATE KEY BLOCK-----
public_key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
[paste public key content]
-----END PGP PUBLIC KEY BLOCK-----
trust_db: |
[paste trust database content] -
Keys are automatically deployed to:
~/.gnupg/private-key.asc(mode 0600)~/.gnupg/public-key.asc(mode 0644)~/.gnupg/trust-db.txt(mode 0600)
Troubleshooting
Common Issues
Cannot Decrypt Secrets
Problem: sops: error: cannot decrypt
Solutions:
- Verify age key exists:
ls -la ~/.config/sops/age/keys.txt - Check public key is in
.sops.yaml - Re-encrypt secrets:
sops updatekeys secrets/secrets.yaml
Permission Denied
Problem: Secrets file has wrong permissions
Solutions:
- Check file ownership in secret configuration
- Verify user exists before secret deployment
- Use
neededForUsers = truefor user password secrets
Keys Not Found
Problem: Age keys missing after system rebuild
Solutions:
- Restore from backup
- Regenerate and re-encrypt all secrets
- Check key file path configuration
Debugging Commands
# Check SOPS configuration
sops -d secrets/secrets.yaml
# Verify age key (platform-specific)
# Darwin
age-keygen -y /Users/roelc/.config/sops/age/keys.txt
# Linux
age-keygen -y /home/roelc/.config/sops/age/keys.txt
# Check deployed secrets
ls -la /run/secrets/
ls -la /run/secrets/users/
ls -la /run/secrets/authorized_keys/
ls -la /run/secrets/gpg/
# Test specific secret decryption
sudo cat /run/secrets/users/roelc
sudo cat /run/secrets/wireless
sudo cat /run/secrets/gpg/private_key
# Check SSH authorized keys deployment
ls -la /home/roelc/.ssh/authorized_keys # Linux
ls -la /Users/roelc/.ssh/authorized_keys # Darwin
ls -la /root/.ssh/authorized_keys # Linux only
# Check GPG key deployment
ls -la ~/.gnupg/private-key.asc
ls -la ~/.gnupg/public-key.asc
ls -la ~/.gnupg/trust-db.txt
# Verify GPG key import
gpg --list-keys
gpg --list-secret-keys
Security Best Practices
Key Management
- Backup age keys securely
- Use separate keys for different environments
- Rotate keys periodically
- Never commit private keys to version control
Secret Organization
- Use descriptive secret names
- Group related secrets logically
- Document secret purposes
- Implement least-privilege access
Operational Security
- Audit secret access regularly
- Monitor for unauthorized changes
- Use temporary secrets when possible
- Implement secret rotation policies
Integration with NixOS/Darwin
Automatic Deployment
Secrets are automatically deployed during system builds to /run/secrets/:
# NixOS systems (chad, legion, ghost)
sudo nixos-rebuild switch --flake .#hostname
# Darwin systems (macOS)
darwin-rebuild switch --flake .#hostname
Service Integration
Services can reference secrets through the /run/secrets/ path:
# Example: Using wireless secret in networking configuration
networking.wireless = {
enable = true;
networks."YourNetworkName".pskFile = config.sops.secrets.wireless.path;
};
User Environment
GPG keys are automatically imported into the user's GPG keyring during system activation.
Advanced Topics
Adding New Machines
When adding a new machine to the configuration:
-
Generate age key on new machine:
# Keys are auto-generated, or manually:
age-keygen -o ~/.config/sops/age/keys.txt
age-keygen -y ~/.config/sops/age/keys.txt # Get public key -
Add to
.sops.yaml:keys:
- &roelc_key age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- &new_machine_key age1yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
creation_rules:
- path_regex: secrets/secrets.yaml$
key_groups:
- age:
- *roelc_key
- *new_machine_key -
Re-encrypt secrets:
sops updatekeys secrets/secrets.yaml
Machine-Specific Secrets
For secrets that only apply to specific machines, you can extend the configuration:
# In machine-specific configuration
sops.secrets = lib.mkMerge [
# Standard secrets from shared/utils/sops.nix
# Machine-specific secrets
(lib.mkIf (config.networking.hostName == "specific-machine") {
"machine-specific/secret" = {
path = "/etc/machine-specific-secret";
mode = "0600";
};
})
];
Secret Backup Strategy
- Backup age keys - Store securely offline
- Version control - All encrypted secrets are in git
- Key rotation - Periodically generate new age keys
- Documentation - Keep track of what secrets exist and their purpose