This is a cool trick for those playing around with Nix’s module system. While developing nix-config-modules, I ran into a semi-unique issue: In the module system I defined a set of hosts and a separate, general set of apps, and hosts could define which apps they could import.

To generate this subset of app configurations, I wanted to be able to re-evaluate all of my app modules with a host argument. In other words, I wanted to be able to write modules like:

{ host, ... }:
{
  app.emacs = {
    enable = host.kind == "nixos";
  };
}

And then essentially I would call lib.evalModules on the apps modules with the host argument substituted with each host I had configured.

What I needed was, in my module system I needed to grab all the modules that defined my modules. Fortunately Nix makes this easy: every module gets a moduleType argument that includes the definition of all modules. So if you need to reevaluate all of your modules with a special additional configuration, all you need to do is:

{ lib, moduleType, ... }:
# < ... >
lib.evalModules {
  modules = moduleType.getSubModules ++ [
    { _module.args.host = myHost; }
  ];
};

Of course you’d need to be extremely careful as there’s a huge risk of infinite recursion here, but it can be pretty handy.