Install agenix in "environment.systemPackages" on nixos with flakes

I am trying to install agenix on nixos. I use a flake for the configuration.

{
  description = "System configuration";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-21.11";
    
    #for secrets
    agenix.url = "github:ryantm/agenix";
    agenix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, agenix, ... }:
  let
    system = "x86_64-linux";

    pkgs = import nixpkgs {
      inherit system;
      config = { allowUnfree = true; };
    };

    lib = nixpkgs.lib;
  in {
    nixosConfigurations = {
      acamar = lib.nixosSystem {
        inherit system;
        
        modules = [
          ./systems/acamar/configuration.nix
          agenix.nixosModules.age
        ];
      };
    };
  };
}
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  ..... Network, boot , other stuff here

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = [
    pkgs.git
    pkgs.htop
    pkgs.tmux
    agenix.defaultPackage.x86_64-linux
  ];


According to the instructions here, environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ]; should allow me to install agenix on the system. However, I get this error message:

error: undefined variable 'agenix'

       at /nix/store/np0l57isw4a12q0q2a75dpb8c34prx7d-source/systems/acamar/configuration.nix:111:5:

          110|     pkgs.tmux
          111|     agenix.defaultPackage.x86_64-linux
             |     ^
          112|   ];
(use '--show-trace' to show detailed location information)

If I uncomment the line from systemPackages a rebuild works as expected. I probably need to pass the variable somehow? I just dont now where or how to do this. Adding “agenix” as an input to configuration.nix does not work.

One option is writing another simple module directly in flake.nix:

        ...
        modules = [
          { environment.systemPackages = [ agenix.defaultPackage.${system} ]; }
          ./systems/acamar/configuration.nix
          agenix.nixosModules.age
        ];
        ...

So that agenix is defined in the scope.

But a better solution would be to use specialArgs or _module.args to pass all the flake inputs or just agenix to each module as custom arguments. The latter is preferable to the former in that it allows overriding but it can result in infinite recursion. Here is another discussion about this topic.

2 Likes

The nicest way of doing this IMO is to use the overlay:

{
  description = "System configuration";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-21.11";
    
    #for secrets
    agenix.url = "github:ryantm/agenix";
    agenix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, agenix, ... }:
  let
    system = "x86_64-linux";
    overlays = [ agenix.overlay ];

    pkgs = import nixpkgs {
      inherit overlays system; # Don't forget this
      config = { allowUnfree = true; };
    };

    lib = nixpkgs.lib;
  in {
    nixosConfigurations = {
      acamar = lib.nixosSystem {
        inherit pkgs system; # Or this ;)
        
        modules = [
          ./systems/acamar/configuration.nix
          agenix.nixosModules.age
        ];
      };
    };
  };
}

That will add this overlay to your pkgs attrset, which means pkgs.agenix is how you access the package.

This scales nicely across different flakes as well (pretty much all of them supply overlays), as well as non-flake third party repos, and sets you up to create your own overlays for downstream packages and modules.

I personally also just find it cleaner than hacking around with specialArgs and _module.args, given one of those is marked private and the other has a big warning to use the private one instead.

The downside is that this pollutes your pkgs namespace, but that is arguably what you want.

You could also set nixpkgs.overlays, but I think modifying the actual pkgs before it is evaluated is cleaner.

Edit: added inherit pkgs, since that’s clearly necessary as pointed out by @SlaterTh90, but missing from my personal config because I do use the option :stuck_out_tongue:

5 Likes

Thanks, that solved my problem! I also had to add “inherit pkgs” to the lib.nixosSystem section. Apparently that is necessary to pass the overlay to the configuration-

1 Like