Key Management
This guide covers managing encryption and decryption keys for nixos-artifacts-agenix.
Key Types
nixos-artifacts-agenix supports multiple key types:
| Key Type | Format | Use Case |
|---|---|---|
SSH public key |
|
Most common, works with SSH host keys and user keys |
Age public key |
|
Pure age format, generated by |
YubiKey age key |
|
Hardware security keys |
Obtaining Keys
Host Keys (NixOS)
Retrieve the host’s public SSH key:
ssh-keyscan <hostname> | grep ssh-ed25519
Or from a known host:
ssh-keyscan localhost | grep ssh-ed25519
For age keys, convert SSH public keys:
nix run nixpkgs#ssh-to-age -- < /etc/ssh/ssh_host_ed25519_key.pub
Configuring Keys
NixOS Configuration
artifacts.config.agenix = {
# Host's public key (required)
publicHostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...";
# Additional keys that can decrypt (optional)
publicUserKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@laptop"
"age1yubikey1q0..."
];
};
Home Manager Configuration
artifacts.config.agenix = {
# Keys used to encrypt (required for Home Manager)
publicUserKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@laptop"
];
# Paths to private keys for decryption (required)
identityPaths = [
"${config.home.homeDirectory}/.ssh/id_ed25519"
"${config.home.homeDirectory}/.config/age/key.txt"
];
};
Key Rotation
When you need to rotate encryption keys:
-
Add the new key to configuration:
publicUserKeys = [ "ssh-ed25519 AAAA...new-key" "ssh-ed25519 AAAA...old-key" # Keep old key during transition ]; -
Re-encrypt all secrets using the TUI:
Run the TUI and serialize your artifacts again. This encrypts secrets with ALL configured keys, including the new one.
-
Verify decryption works (on the target machine):
sudo agenix --decrypt /path/to/secret.age --identity /etc/ssh/ssh_host_ed25519_key -
Remove the old key from configuration:
publicUserKeys = [ "ssh-ed25519 AAAA...new-key" # Old key removed ]; -
Commit and deploy the updated configuration.
Re-encrypting After Key Changes
If keys change but secrets aren’t updated, re-serialize using the TUI to regenerate encrypted files with current keys.
Multiple Machines / Users
For secrets shared across multiple machines:
Separate Secret Files
Each machine stores its own copy:
secrets/per-machine/laptop/wifi/psk.age
secrets/per-machine/server/wifi/psk.age
Shared Secrets
Use the shared = true artifact option:
artifacts.store.wifi-password = {
shared = true; # Encrypted with ALL keys from all referencing machines
files = { "psk" = { }; };
};
Configure all machines to include their public keys:
# On laptop
artifacts.config.agenix = {
publicHostKey = "ssh-ed25519 AAAA...laptop...";
publicUserKeys = [ "ssh-ed25519 AAAA...user..." ];
};
# On server
artifacts.config.agenix = {
publicHostKey = "ssh-ed25519 AAAA...server...";
publicUserKeys = [ "ssh-ed25519 AAAA...user..." ];
};
Troubleshooting
"age: error: no identity matched any of the file’s recipients"
The secret was encrypted with keys you don’t have. Solutions:
-
Verify your key is in
publicUserKeys(for Home Manager) orpublicHostKey(for NixOS) -
Re-serialize the secrets using the TUI with your current key configuration
Decryption Fails at Runtime
Check that the decryption identity exists:
-
NixOS: Host SSH key at
/etc/ssh/ssh_host_ed25519_key -
Home Manager: Path configured in
identityPaths
Verify the identity can decrypt:
# For SSH keys
agenix --decrypt secrets/per-machine/myhost/mysecret/file.age \
--identity /etc/ssh/ssh_host_ed25519_key
# For age keys
age --decrypt -i ~/.config/age/key.txt secrets/per-user/myuser/mysecret/file.age