Why is agenix undefined after adding the module to my flake?

​Can anyone help me understand what’s missing to add agenix to my flake-utils-plus flake?

I believe I followed the instructions in the agenix readme correctly but it says undefined variable 'agenix' when I build my repo with nixos-rebuild build-vm --flake .#Rick.

Here is the flake.nix and repo: flake-utils-agenix-issue/flake.nix at ae6aeaa274a0c925ce0f8a7925fc76b7747438b0 · ParetoOptimalDev/flake-utils-agenix-issue · GitHub

{
  description = "Very simple flake-utils-plus flake with home-manager and home-managers spotifyd with agenix secrets";  

  inputs = {
    nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
    utils.url = github:gytis-ivaskevicius/flake-utils-plus;
    home-manager = {
      url = github:nix-community/home-manager/release-21.05;
      inputs.nixpkgs.follows = "nixpkgs";
    };
    agenix.url = github:ryantm/agenix;
  };

  outputs = inputs@{ self, nixpkgs, utils, home-manager, agenix }:

    utils.lib.mkFlake {
      inherit self inputs;

      channelsConfig.allowUnfree = true;

      hostDefaults.modules = [
        { home-manager.users.morty.home.stateVersion = "21.05"; }

        agenix.nixosModule
        home-manager.nixosModules.home-manager
      ];

      hosts.Rick.modules = [
        ./hosts/Rick.nix
        agenix.nixosModule
      ];

    };
}

Here is what running it looks like:

$ nixos-rebuild build-vm --flake .#Rick --show-trace
building the system configuration...
error: undefined variable 'agenix'

       at /nix/store/wnsxhqh5w9l4ikkdhxbqls7jgw818v4k-source/hosts/Rick.nix:8:34:

            7|
            8|   environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ];
             |                                  ^
            9|

       … while evaluating 'isFunction'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/trivial.nix:448:16:

          447|   */
          448|   isFunction = f: builtins.isFunction f ||
             |                ^
          449|     (f ? __functor && isFunction (f.__functor f));

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:486:78:

          485|
          486|   applyModuleArgsIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
             |                                                                              ^
          487|     let

       … while evaluating 'applyModuleArgsIfFunction'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:486:39:

          485|
          486|   applyModuleArgsIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
             |                                       ^
          487|     let

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:386:59:

          385|           throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}"
          386|         else unifyModuleSyntax (toString m) (toString m) (applyModuleArgsIfFunction (toString m) (import m) args);
             |                                                           ^
          387|

       … while evaluating 'unifyModuleSyntax'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:455:34:

          454|      of ‘options’, ‘config’ and ‘imports’ attributes. */
          455|   unifyModuleSyntax = file: key: m:
             |                                  ^
          456|     let

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:386:14:

          385|           throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}"
          386|         else unifyModuleSyntax (toString m) (toString m) (applyModuleArgsIfFunction (toString m) (import m) args);
             |              ^
          387|

       … while evaluating 'loadModule'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:380:53:

          379|       # Like unifyModuleSyntax, but also imports paths and calls functions if necessary
          380|       loadModule = args: fallbackFile: fallbackKey: m:
             |                                                     ^
          381|         if isFunction m || isAttrs m then

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:421:22:

          420|           let
          421|             module = loadModule args parentFile "${parentKey}:anon-${toString n}" x;
             |                      ^
          422|             collectedImports = collectStructuredModules module._file module.key module.imports args;

       … while evaluating the attribute 'disabled'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:416:13:

          415|           collectResults = modules: {
          416|             disabled = concatLists (catAttrs "disabled" modules);
             |             ^
          417|             inherit modules;

       … while evaluating anonymous lambda

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:440:31:

          439|           disabledKeys = map moduleKey disabled;
          440|           keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
             |                               ^
          441|         in map (attrs: attrs.module) (builtins.genericClosure {

       … from call site

       … while evaluating 'filterModules'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:434:36:

          433|       # modules recursively. It returns the final list of unique-by-key modules
          434|       filterModules = modulesPath: { disabled, modules }:
             |                                    ^
          435|         let

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:447:7:

          446|     in modulesPath: initialModules: args:
          447|       filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
             |       ^
          448|

       … while evaluating anonymous lambda

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:446:37:

          445|
          446|     in modulesPath: initialModules: args:
             |                                     ^
          447|       filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:290:25:

          289|       merged =
          290|         let collected = collectModules
             |                         ^
          291|           (specialArgs.modulesPath or "")

       … while evaluating 'reverseList'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/lists.nix:394:17:

          393|   */
          394|   reverseList = xs:
             |                 ^
          395|     let l = length xs; in genList (n: elemAt xs (l - n - 1)) l;

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:294:33:

          293|           ({ inherit lib options config specialArgs; } // specialArgs);
          294|         in mergeModules prefix (reverseList collected);
             |                                 ^
          295|

       … while evaluating 'byName'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:562:25:

          561|       */
          562|       byName = attr: f: modules:
             |                         ^
          563|         zipAttrsWith (n: concatLists)

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:579:21:

          578|       # an attrset 'name' => list of submodules that declare ‘name’.
          579|       declsByName = byName "options" (module: option:
             |                     ^
          580|           [{ inherit (module) _file; options = option; }]

       … while evaluating the attribute 'matchedOptions'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:658:14:

          657|     in {
          658|       inherit matchedOptions;
             |              ^
          659|

       … while evaluating 'mapAttrsRecursiveCond'

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/attrsets.nix:393:36:

          392|   */
          393|   mapAttrsRecursiveCond = cond: f: set:
             |                                    ^
          394|     let

       … from call site

       at /nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/lib/modules.nix:302:28:

          301|           # For definitions that have an associated option
          302|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                            ^
          303|

I’m sorry that this isn’t exactly super constructive, but I gave up after 5 minutes. I love Nix, I love refactoring Nix, but some of these “flake frameworks” are… I’m just not sure they’re a great starting point for folks.

My helpful advice is that most folks using flakes seem to wind up having specialArgs = { inherit inputs; }; or somethng similar in their call to nixosSystem, etc. This then makes inputs available to nixos modules as a function input, thereby giving you access to flake inputs down inside a nixos host configuration, as it seems you want. I guess you’ll need to figure out how to do that in the flakes-utils-plus framework. :confused:

1 Like

This helps:

diff --git a/flake.nix b/flake.nix
index 9965d49..8ea5927 100644
--- a/flake.nix
+++ b/flake.nix
@@ -27,7 +27,7 @@

       hosts.Rick.modules = [
         ./hosts/Rick.nix
-        agenix.nixosModule
+        # agenix.nixosModule
       ];

     };
diff --git a/hosts/Rick.nix b/hosts/Rick.nix
index 2da981c..5bdac22 100644
--- a/hosts/Rick.nix
+++ b/hosts/Rick.nix
@@ -1,11 +1,11 @@
-{ config, pkgs, ... }:
+{ config, inputs, pkgs, ... }:

 {
   # Root file system and bootloader is required for CI to build system configuration
   boot.loader.grub.devices = [ "nodev" ];
   fileSystems."/" = { device = "test"; fsType = "ext4"; };

-  environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ];
+  environment.systemPackages = [ inputs.agenix.defaultPackage.x86_64-linux ];

   users = {
     mutableUsers = false;

(I commented out the duplicate module, as I had errors for properties defined several times).

The problem is that the agenix variable isn’t automagically accessible in your hosts/Rick.nix submodule - it only has access to what’s passed to it (config, pkgs).

You can access agenix as I’ve done through inputs, or you can pass it through specialArgs, in which case it would be passed down to the modules as an argument (similar to config, pkgs, etc.).

Thank you, I think I can move forward with that. A question I think I can eventually answer and am currently working out though is:

Doesn’t removing agenix.nixosModule mean I can’t use the agenix module anymore? Or I guess it means that I have to prepend inputs.agenix or use specialArgs?

So hosts.Rick.modules and inputs.agenix passed to hosts/Rick.nix are mutually exclusive, because both gives:

error: The option `age.identityPaths' in `/nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/flake.nix' is already declared in `/nix/store/8x9s4zv7dzmwxmm8lhsxk3nf8lxlh52q-source/flake.nix'.

No, it was hostDefaults.modules and hosts.Rick.modules that were conflicting for me, because both included agenix.nixosModule, and that results in same config properties being defined twice.

Including the module (or not) does not have much to do with inputs (unless there’s some extra magic in flake-utils-plus that I’m not familiar with). You can include the agenix package in your systemPackages, or import (and enable) the agenix NixOS module, or both, or neither - these are distinct things. And specialArgs only controls what is passed as arguments to modules when evaluating them.