agenix/doc/reference.md
Ryan Mulligan 5c1198a352 feat: switch from rage to age
Why
===
* Someone said age works better with password protected keys,
requiring entering the password less often.
* We switched to rage from age in
07ce686870
because it was limiting recipients to 20. This was fixed
https://github.com/FiloSottile/age/issues/139

What changed
===
* Switch from rage back to age (the reference implementation) in all
the spots
* Update the docs to show how to switch back to Rage
* Skip keys that are empty files, which fixes the integration test.
2023-12-23 14:09:16 -08:00

5.8 KiB

Reference

age module reference

age.secrets

age.secrets attrset of secrets. You always need to use this configuration option. Defaults to {}.

age.secrets.<name>.file

age.secrets.<name>.file is the path to the encrypted .age for this secret. This is the only required secret option.

Example:

{
  age.secrets.monitrc.file = ../secrets/monitrc.age;
}

age.secrets.<name>.path

age.secrets.<name>.path is the path where the secret is decrypted to. Defaults to /run/agenix/<name> (config.age.secretsDir/<name>).

Example defining a different path:

{
  age.secrets.monitrc = {
    file = ../secrets/monitrc.age;
    path = "/etc/monitrc";
  };
}

For many services, you do not need to set this. Instead, refer to the decryption path in your configuration with config.age.secrets.<name>.path.

Example referring to path:

{
  users.users.ryantm = {
    isNormalUser = true;
    passwordFile = config.age.secrets.passwordfile-ryantm.path;
  };
}

builtins.readFile anti-pattern

{
  # Do not do this!
  config.password = builtins.readFile config.age.secrets.secret1.path;
}

This can cause the cleartext to be placed into the world-readable Nix store. Instead, have your services read the cleartext path at runtime.

age.secrets.<name>.mode

age.secrets.<name>.mode is permissions mode of the decrypted secret in a format understood by chmod. Usually, you only need to use this in combination with age.secrets.<name>.owner and age.secrets.<name>.group

Example:

{
  age.secrets.nginx-htpasswd = {
    file = ../secrets/nginx.htpasswd.age;
    mode = "770";
    owner = "nginx";
    group = "nginx";
  };
}

age.secrets.<name>.owner

age.secrets.<name>.owner is the username of the decrypted file's owner. Usually, you only need to use this in combination with age.secrets.<name>.mode and age.secrets.<name>.group

Example:

{
  age.secrets.nginx-htpasswd = {
    file = ../secrets/nginx.htpasswd.age;
    mode = "770";
    owner = "nginx";
    group = "nginx";
  };
}

age.secrets.<name>.group

age.secrets.<name>.group is the name of the decrypted file's group. Usually, you only need to use this in combination with age.secrets.<name>.owner and age.secrets.<name>.mode

Example:

{
  age.secrets.nginx-htpasswd = {
    file = ../secrets/nginx.htpasswd.age;
    mode = "770";
    owner = "nginx";
    group = "nginx";
  };
}

age.secrets.<name>.symlink is a boolean. If true (the default), secrets are symlinked to age.secrets.<name>.path. If false, secerts are copied to age.secrets.<name>.path. Usually, you want to keep this as true, because it secure cleanup of secrets no longer used. (The symlink will still be there, but it will be broken.) If false, you are responsible for cleaning up your own secrets after you stop using them.

Some programs do not like following symlinks (for example Java programs like Elasticsearch).

Example:

{
  age.secrets."elasticsearch.conf" = {
    file = ../secrets/elasticsearch.conf.age;
    symlink = false;
  };
}

age.secrets.<name>.name

age.secrets.<name>.name is the string of the name of the file after it is decrypted. Defaults to the <name> in the attrpath, but can be set separately if you want the file name to be different from the attribute name part.

Example of a secret with a name different from its attrpath:

{
  age.secrets.monit = {
    name = "monitrc";
    file = ../secrets/monitrc.age;
  };
}

age.ageBin

age.ageBin the string of the path to the age binary. Usually, you don't need to change this. Defaults to age/bin/age.

Overriding age.ageBin example:

{pkgs, ...}:{
    age.ageBin = "${pkgs.age}/bin/age";
}

age.identityPaths

age.identityPaths is a list of paths to recipient keys to try to use to decrypt the secrets. By default, it is the rsa and ed25519 keys in config.services.openssh.hostKeys, and on NixOS you usually don't need to change this. The list items should be strings ("/path/to/id_rsa"), not nix paths (../path/to/id_rsa), as the latter would copy your private key to the nix store, which is the exact situation agenix is designed to avoid. At least one of the file paths must be present at runtime and able to decrypt the secret in question. Overriding age.identityPaths example:

{
    age.identityPaths = [ "/var/lib/persistent/ssh_host_ed25519_key" ];
}

age.secretsDir

age.secretsDir is the directory where secrets are symlinked to by default.Usually, you don't need to change this. Defaults to /run/agenix.

Overriding age.secretsDir example:

{
    age.secretsDir = "/run/keys";
}

age.secretsMountPoint

age.secretsMountPoint is the directory where the secret generations are created before they are symlinked. Usually, you don't need to change this. Defaults to /run/agenix.d.

Overriding age.secretsMountPoint example:

{
    age.secretsMountPoint = "/run/secret-generations";
}

agenix CLI reference

agenix - edit and rekey age secret files

agenix -e FILE [-i PRIVATE_KEY]
agenix -r [-i PRIVATE_KEY]

options:
-h, --help                show help
-e, --edit FILE           edits FILE using $EDITOR
-r, --rekey               re-encrypts all secrets with specified recipients
-d, --decrypt FILE        decrypts FILE to STDOUT
-i, --identity            identity to use when decrypting
-v, --verbose             verbose output

FILE an age-encrypted file

PRIVATE_KEY a path to a private SSH key used to decrypt file

EDITOR environment variable of editor to use when editing FILE

If STDIN is not interactive, EDITOR will be set to "cp /dev/stdin"

RULES environment variable with path to Nix file specifying recipient public keys.
Defaults to './secrets.nix'