4.1 KiB
Agenix Secret Management Guide
A guide for creating and managing encrypted secrets using agenix in the nixos-config project.
Prerequisites
- SSH key pair (ed25519 or rsa) in
~/.ssh/ - Access to the nixos-config repository
- Secret added to
secrets.nixwith appropriate public keys
Creating a New Secret
Step 1: Add Secret to secrets.nix
Edit secrets.nix and add a new entry:
"secrets/<your-secret-name>.age".publicKeys = systems ++ users;
Where:
<your-secret-name>is the desired filename (without.age)systems= hosts that can decrypt this secretusers= users that can decrypt this secret
Example:
"secrets/my-service-api-key.age".publicKeys = systems ++ users;
Step 2: Create the Encrypted Secret
Navigate to the nixos-config directory:
cd ~/p/NIX/nixos-config
Generate a secure random token (if needed):
head -c 32 /dev/urandom | base64 | tr -d '\n'
Or use a specific value:
echo -n "your-secret-value-here" > /tmp/token.txt
Encrypt and create the secret file:
cat /tmp/token.txt | RULES=./secrets.nix nix develop . --command sh -c 'agenix -e secrets/<your-secret-name>.age'
The -e flag encrypts stdin content into the age file. If no stdin is provided, agenix opens your editor.
Step 3: Verify the Secret
Decrypt to verify:
RULES=./secrets.nix nix develop . --command agenix -d secrets/<your-secret-name>.age
You should see your secret value printed to stdout.
Step 4: Use in NixOS Configuration
Reference the secret in your service config:
{ config, ... }:
{
# For environment files
environmentFiles = [ config.age.secrets."my-secret-name".path ];
# For file-based secrets
environmentFile = config.age.secrets."my-secret-name".path;
}
The secret will be available at /run/agenix/<your-secret-name> when the system builds.
Common Patterns
Token-Based Registration (e.g., Tuwunel)
# secrets.nix
"secrets/tuwunel-registration-token.age".publicKeys = systems ++ users;
# services/tuwunel.nix
settings.global = {
allow_registration = true;
registration_token_file = config.age.secrets."tuwunel-registration-token".path;
};
API Keys via Environment Files
# secrets.nix
"secrets/my-service-env.age".publicKeys = systems ++ users;
Create my-service-env.age containing:
MY_SERVICE_API_KEY=your-key-here
DATABASE_URL=postgres://...
Reference in config:
environmentFiles = [ config.age.secrets."my-service-env".path ];
File-Based Secrets
For binary files or specific file paths:
settings = {
tls.cert = config.age.secrets."tls-cert".path;
tls.key = config.age.secrets."tls-key".path;
};
Agenix Command Reference
| Command | Description |
|---|---|
agenix -e <file.age> |
Edit/create encrypted secret (opens editor or uses stdin) |
agenix -d <file.age> |
Decrypt and print to stdout |
agenix -r |
Re-encrypt all secrets (after changing public keys) |
agenix --validate-config |
Validate secrets.nix syntax |
Environment Variables
| Variable | Default | Description |
|---|---|---|
RULES |
./secrets.nix |
Path to secrets.nix file |
EDITOR |
$EDITOR |
Editor for interactive editing |
Troubleshooting
"No identity found to decrypt"
Cause: No SSH private key available.
Solution: Ensure your private key is in ~/.ssh/:
~/.ssh/id_rsa~/.ssh/id_ed25519- Or specify with
-i /path/to/private/key
"Failed to find config root"
Cause: Agenix can't find secrets.nix.
Solution: Use RULES=./secrets.nix or run from the nixos-config directory.
Rekeying Secrets
After adding new public keys to secrets.nix, re-encrypt all secrets:
cd ~/p/NIX/nixos-config
RULES=./secrets.nix nix develop . --command agenix -r
Security Notes
- Never commit plaintext secrets to git
- Always use
secrets.nixfor encryption keys - Include only necessary hosts/users in public keys
- Rotate secrets periodically
- Use
agenix -rafter modifying public keys