Advanced Secret Management - bcl1713/nixos GitHub Wiki
Secret Management with Agenix
This guide explains how to manage sensitive information securely using Agenix within this NixOS configuration.
Introduction to Agenix
Agenix is a secrets management tool for NixOS that allows you to securely store sensitive data in your git repository. It uses age encryption to ensure that secrets are:
- Encrypted using public keys
- Decryptable only by authorized private keys
- Safe to store in version control
- Easily integrated with NixOS and Home Manager
The main benefits of using Agenix compared to other solutions:
- Security: Strong encryption based on age
- Simplicity: Simple key management and straightforward usage
- Integration: Seamless NixOS and Home Manager integration
- Version Control: Safe to commit encrypted secrets to Git
Setting Up Agenix
Installation
Agenix is already included in this configuration. The module is imported in flake.nix
:
# In flake.nix
inputs = {
agenix.url = "github:ryantm/agenix";
agenix.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { nixpkgs, home-manager, agenix, ... }@inputs: {
nixosConfigurations = {
nixbook = lib.nixosSystem {
# ...
modules = [
./profiles/${systemSettings.profile}/configuration.nix
agenix.nixosModules.default
];
};
};
};
And in the home configuration:
# In profiles/personal/home.nix
{
imports = [ ../../user/packages inputs.agenix.homeManagerModules.default ];
age = {
identityPaths = [ "/home/${userSettings.username}/.ssh/id_ed25519" ];
secrets = {
personal-email = { file = ../../secrets/personal-email.age; };
};
};
}
Key Configuration
To set up your encryption keys:
-
Generate an SSH key if you don't already have one:
ssh-keygen -t ed25519 -C "[email protected]"
-
Configure secret recipients in
secrets/secrets.nix
:let # Your SSH public key yourusername = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; # Your system's host key (optional, for system secrets) hostname = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; allUsers = [ yourusername hostname ]; in { # Define access for each secret "personal-email.age".publicKeys = allUsers; }
-
Verify your identity path is correctly set in your configuration:
age.identityPaths = [ "/home/yourusername/.ssh/id_ed25519" ];
Managing Secrets
Creating Secrets
To create a new secret:
-
Create a plain text file with your secret:
echo "secret-data" > /tmp/mysecret
-
Encrypt the secret using agenix:
agenix -e secrets/mysecret.age -i /tmp/mysecret
-
Add the secret to your secrets configuration in
secrets/secrets.nix
:"mysecret.age".publicKeys = allUsers;
-
Add the secret to your home or system configuration:
For Home Manager:
# In profiles/personal/home.nix age.secrets.mysecret = { file = ../../secrets/mysecret.age; };
For system-wide:
# In profiles/personal/secrets.nix age.secrets.mysecret = { file = ../../secrets/mysecret.age; owner = "yourusername"; group = "users"; mode = "0400"; };
Editing Secrets
To edit an existing secret:
# Edit with temporary decryption
agenix -e secrets/mysecret.age
# Or decrypt to a file, edit, then re-encrypt
agenix -d secrets/mysecret.age > /tmp/mysecret
# Edit /tmp/mysecret
agenix -e secrets/mysecret.age -i /tmp/mysecret
# Remember to securely delete /tmp/mysecret
shred -u /tmp/mysecret
Using Secrets in Your Configuration
Accessing Secrets in Home Manager
# Access a secret for use with a service
programs.someprogram = {
enable = true;
passwordFile = config.age.secrets.mysecret.path;
};
# Dynamically load secret content during activation
home.activation.loadSecret = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
if [ -n "${config.age.secrets.mysecret.path}" ](/bcl1713/nixos/wiki/--n-"${config.age.secrets.mysecret.path}"-); then
# Read secret content
SECRET_VALUE=$(cat "${config.age.secrets.mysecret.path}")
# Use the secret
$DRY_RUN_CMD some-command --password "$SECRET_VALUE"
fi
'';
System-wide Secret Usage
# In a system service
services.someservice = {
enable = true;
passwordFile = config.age.secrets.mysecret.path;
};
Example: Email Configuration
The configuration includes an example of secret management for personal email:
-
Secret Definition (in
secrets/secrets.nix
):"personal-email.age".publicKeys = allUsers;
-
Secret Declaration (in
profiles/personal/home.nix
):age.secrets.personal-email = { file = ../../secrets/personal-email.age; };
-
Usage (in
user/packages/apps/development/git.nix
):# Set email from secret file if not explicitly configured home.activation.setGitEmail = lib.hm.dag.entryAfter [ "writeBoundary" ] '' if [[ -z "${cfg.userEmail}" && -n "${ if config.age.secrets ? personal-email then config.age.secrets.personal-email.path else "" }" ]]; then # User hasn't specified an email and the secret exists EMAIL=$(cat "${config.age.secrets.personal-email.path}") $DRY_RUN_CMD ${pkgs.git}/bin/git config --global user.email "$EMAIL" elif [ -n "${cfg.userEmail}" ](/bcl1713/nixos/wiki/--n-"${cfg.userEmail}"-); then # User explicitly set an email, use that $DRY_RUN_CMD ${pkgs.git}/bin/git config --global user.email "${cfg.userEmail}" fi '';
Best Practices
Security Considerations
- Never commit unencrypted secrets to your repository
- Keep your private keys secure
- Use restrictive file permissions (
0400
or0600
) - Clean up temporary files containing sensitive data
Secret Organization
- Group related secrets together (e.g., all database credentials)
- Use descriptive filenames
- Document the purpose of each secret in comments
Backup Strategies
- Ensure your private keys are backed up securely
- Consider using multiple recipient keys for redundancy
- Document key locations for disaster recovery
Collaboration
When collaborating with others:
- Add their public keys to
secrets/secrets.nix
- Re-encrypt secrets for multiple recipients
- Establish a secure process for key exchange
Troubleshooting
Common Issues
-
"Failed to decrypt":
- Ensure private key is at the correct location
- Verify you are a recipient for the secret
- Check file permissions on your private key
-
"Secret not found":
- Check the path in your configuration
- Verify secret is properly declared
-
Permission Issues:
- Check owner/group settings
- Verify mode settings (permissions)
Further Reading
Related Pages
- Advanced-System-Updates - Managing system updates
- Security-Best-Practices - Overall security recommendations
- Contributing-Guidelines - Contributing with secrets in the repository