Noureddine RAMDI / Agenix: secure secret management integrated with NixOS and age encryption

Created Sun, 26 Apr 2026 17:51:11 +0000 Modified Sat, 23 May 2026 20:41:27 +0000

ryantm/agenix

Secrets management is a tricky problem in infrastructure as code, especially when your deployment tool emphasizes immutability and reproducibility, like NixOS. Agenix tackles this by combining the age encryption tool with Nix’s declarative model, allowing secrets to coexist safely in the Nix store and be decrypted automatically during system activation. This approach addresses the common pain point of storing secrets encrypted yet making them available seamlessly and reproducibly on NixOS machines.

integrating age encryption with nixos for secret management

Agenix is a Nix library and command-line tool designed explicitly for managing secrets securely within NixOS environments. It leverages SSH public-private key pairs alongside the age encryption tool to encrypt secrets into .age files. These encrypted secrets are then stored safely in the Nix store.

The core architectural idea is that during NixOS system activation, the secrets are decrypted automatically on the target machine using its private SSH keys. The decrypted secrets are then mounted to a well-known location on the filesystem, making them accessible to services or configuration without exposing them in the store or config files in plaintext.

This design tightly integrates with Nix’s declarative configuration and package management model. Since the secrets are stored as encrypted artifacts in the Nix store, they benefit from the store’s immutability and content-addressed paths. The decryption step on activation ensures that secrets are never exposed in plaintext outside the target machine’s volatile runtime environment.

From a technology stack perspective, Agenix is implemented in Nix language and uses the age encryption tool, known for its simplicity and strong cryptographic guarantees. It relies on SSH keys for authentication, which is natural given NixOS’s typical system administration practices.

architectural clarity and tradeoffs in the codebase

What stands out technically is how Agenix treats secrets as first-class citizens in the Nix deployment pipeline without compromising security principles. This is not trivial since the Nix store is inherently immutable and often globally readable by design.

The codebase, while written in Nix language, is surprisingly clean and modular. It provides modules to be imported into NixOS configurations as well as a CLI for encrypting secrets conveniently. This dual interface caters well to both declarative system management and interactive secret creation.

One tradeoff is the reliance on SSH keys and the age ecosystem. While this fits well within the NixOS admin workflow, it may not suit setups that use other secret management backends or key management systems. Additionally, the decrypted secrets exist on the target machine only at runtime and must be handled with care by consuming services.

Another consideration is that while the approach avoids plaintext secrets in the store, it requires managing private keys securely on all target machines. This is standard practice but worth highlighting.

Overall, the code quality and documentation provide a decent developer experience (DX). The Nix modules abstract away complexity, and the CLI commands are straightforward, making it accessible for Nix users familiar with the ecosystem.

quick start with agenix

Installation

Install via niv

$ niv add ryantm/agenix
Install module via niv
{
  imports = [ "${(import ./nix/sources.nix).agenix}/modules/age.nix" ];
}
Install home-manager module via niv
{
  imports = [ "${(import ./nix/sources.nix).agenix}/modules/age-home.nix" ];
}
Install CLI via niv
{
  environment.systemPackages = [ (pkgs.callPackage "${(import ./nix/sources.nix).agenix}/pkgs/agenix.nix" {}) ];
}

Install via nix-channel

As root run:

$ sudo nix-channel --add https://github.com/ryantm/agenix/archive/main.tar.gz agenix
$ sudo nix-channel --update
Install module via nix-channel
{
  imports = [ <agenix/modules/age.nix> ];
}
Install home-manager module via nix-channel
{
  imports = [ <agenix/modules/age-home.nix> ];
}
Install CLI via nix-channel
{
  environment.systemPackages = [ (pkgs.callPackage <agenix/pkgs/agenix.nix> {}) ];
}

Install via fetchTarball

Install module via fetchTarball

{
  imports = [ "${builtins.fetchTarball "https://github.com/ryantm/agenix/archive/main.tar.gz"}/modules/age.nix" ];
}

or with pinning:

{
  imports = let
    # replace this with an actual commit id or tag
    commit = "298b235f664f925b433614dc33380f0662adfc3f";
  in [
    "${builtins.fetchTarball {
      url = "https://github.com/ryantm/agenix/archive/${commit}.tar.gz";
      # update hash from nix build output
      sha256 = "";
    }}/modules/age.nix"
  ];
}

Install home-manager module via fetchTarball

Add the relevant import similarly as above.

verdict: a solid fit for nixos users who want reproducible secret management

Agenix offers a practical and elegant solution for managing secrets securely in NixOS environments. By combining age encryption with SSH keys and integrating directly into the Nix declarative system, it resolves a common pain point around secret distribution and lifecycle.

It is best suited for users already invested in NixOS and familiar with Nix language and SSH key management. The approach requires trust and good practices around private key security on target machines, which is standard but crucial.

While it won’t replace full-featured secret management systems that integrate with cloud providers or hardware security modules, Agenix fills a niche where secrets need to be packaged and deployed alongside system configuration in a reproducible, auditable way.

For anyone running NixOS in production or managing multiple machines declaratively, Agenix is worth a look. The code quality and documentation strike a good balance between flexibility and usability, and the design aligns well with NixOS principles.


→ GitHub Repo: ryantm/agenix ⭐ 2,320 · Nix