Files
nixos-config/docs/AGENIX-GUIDE.md
2026-04-24 21:38:57 +02:00

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.nix with 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 secret
  • users = 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.nix for encryption keys
  • Include only necessary hosts/users in public keys
  • Rotate secrets periodically
  • Use agenix -r after modifying public keys