Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nix Declarations

The engine generates Nix modules that call mkSecret to declare each secret. These modules are consumed by the NixOS/home-manager configuration that calls agenix.

mkSecret

The core function that declares a single agenix secret:

canixLib.mkSecret {
  name = "can-app-token";
  stack = "home";
  source = secrets.user "can" "app-token";
  targets.home.env = ["APP_TOKEN"];
}

Parameters

ParameterDescription
nameagenix secret name (maps to age file identity)
stack"home", "system", or "forgejo"
sourcePath expression resolving to the .age file
generatorOptional: "passphrase" or "ssh-key"
lengthPassphrase length (32, 48, or 64)
algorithmSSH key algorithm ("ed25519" or "rsa")
targetsDelivery target configuration (stack-specific)
ownerFile owner (for system file delivery)
groupFile group
modeFile mode

Target shapes

Home env delivery:

targets.home.env = ["APP_TOKEN" "API_KEY"];

Home file delivery:

targets.home.file = {
  path = "~/.ssh/deploy-key";
  mode = "600";
};

System env delivery:

targets.system.env = {
  vars = ["VIKUNJA_MAILER_PASSWORD"];
  services = ["vikunja"];
};

System file delivery:

targets.system.file = {
  path = "/run/secrets/vikunja-mailer";
  owner = "vikunja";
  mode = "0400";
};

Forgejo credential delivery:

targets.forgejo.credential = {
  name = "copr-token";
  instances = ["codeberg"];
};

mkSharedSecret

A convenience wrapper that produces a secret declaration for all three stacks from a single source file. Each stack is optional:

canixLib.mkSharedSecret {
  source = ./age/secrets/shared-token.age;
  generator = "passphrase";
  length = 48;

  home = {
    targets.home.env = ["SHARED_TOKEN"];
  };

  system = {
    targets.system.env = {
      vars = ["SHARED_TOKEN"];
      services = ["demo"];
    };
  };
}

Source expressions

The source parameter resolves the .age file path:

# User-scoped secret
secrets.user "can" "app-token"

# Host-scoped secret
secrets.host "thething" "vikunja-mailer"

# Module-scoped secret
secrets.module "forgejo-runner/copr-token"

Generators

lib.mkGenerators {rotateCommand ? "secret-manager rotate"} returns the agenix-rekey generators behind the names mkSecret emits (strong-passphrase, strong-passphrase-48, strong-passphrase-64, ssh-ed25519-pub, ssh-rsa-pub, gpg-key-pair) plus minisign-key-pair. Register them on every agenix module that evaluates these secrets:

age.generators = secret-manager.lib.mkGenerators {};

Passphrases avoid every character special to a systemd EnvironmentFile or a shell export. minisign-key-pair depends on exactly one password secret and encrypts the key with it; rotateCommand is quoted in its error when that password has not been generated yet.