The vars system provides a declarative, reproducible way to manage generated files (especially secrets) in NixOS configurations. This page covers how the pieces fit together.
Declarative generation. Unlike imperative secret management, vars are declared in your NixOS configuration and generated deterministically, making deployments reproducible.
Separation of concerns. Generation logic lives in generator scripts. Storage is handled by pluggable backends (sops, password-store, etc.). Deployment runs through NixOS activation scripts. Access control is enforced through file permissions and ownership.
Composability through dependencies. Generators can depend on outputs from other generators, enabling complex workflows:
# Dependencies create a directed acyclic graph (DAG)
A → B → C
↓
D You can build systems like certificate authorities where intermediate certificates depend on root certificates.
Type safety. Secret files are accessed via .path only (their plaintext content is never readable at evaluation time) and are deployed to /run/secrets/ on the target machine (or /run/secrets-for-users/ when neededFor = "users"). Public files are accessed via either .path or .value and are stored in the nix store. This separation prevents accidental exposure of secrets.
Pluggable storage backends handle encryption/decryption:
sops (default): integrates with Clan's existing sops encryptionpassword-store: for users already using passage: stores secrets encrypted with age recipientscustom: define your own secret storeThere are three ways to trigger generation:
clan vars generate creates any missing vars.clan machines update.--regenerate flag forces regeneration of vars that already exist.neededForThe neededFor option on a file controls when on the target machine a secret becomes available during system activation. Valid values are:
partitioning: deployed before disko runs (e.g. for filesystem encryption keys)activation: deployed before nixos-rebuild / nixos-installusers: deployed before users and groups are created (required for user passwords); stored in /run/secrets-for-users/services: the default; available to normal services at runtimeExample: a user password hash that must exist before the user account is created:
files."user-password-hash" = {
neededFor = "users";
}; Setting share = true on a generator enables cross-machine secret sharing:
Use cases include shared certificate authorities, mesh VPN pre-shared keys, and cluster join tokens.
Complex systems can be built by composing simple generators:
root-ca → intermediate-ca → service-cert
↓
ocsp-responder Each generator focuses on one task, keeping the system modular and testable.
Compared to manual secret management, vars provides: