Import list in `configuration.nix` vs `import` function

Those two ‘import’s are really just two different things with similar name.

Nix’s builtins.import really just loads and inserts a Nix expression from a different file in the place where it is called – you could just replace paste the file contents instead of the import call and it should work the same (modulo file path resolution).

Contrary to local nature of the Nix built-in, imports attribute of NixOS module makes the module system add modules to the list of modules to merge into the global namespace. It also supports wider range of arguments, not just paths, as described above.

But you could decide to sidestep the module system imports and use Nix primitives for loading a module. For example, instead of

{ pkgs, lib, config, options, ...}@args:
{
  imports  = [
    ./quxinator.nix
  ];
  config = {
    foo.bar = true;
  };
}

you could do something like

{ pkgs, lib, config, options, ...}@args:
lib.recursiveUpdate { # BEWARE!!!
  config = {
    foo.bar = true;
  };
}
(import ./quxinator.nix args)

The result might end up the same. Or it might fail horribly – especially if both modules declare overlapping options.

You might try to make merging the modules module-aware:

{ pkgs, lib, config, options, ...}@args:
lib.mkMerge [ # Probably safer but still BEWARE!!!
  {
    config = {
      foo.bar = true;
    };
  }
  (import ./quxinator.nix args)
]

but I give you no warranty and there is no reason to avoid using the module system’s imports feature.

3 Likes