Try to understand Nix function paramters and attributes

Hi there,

I have refactored my NixOS Home-Manager configuration so that a part of it is outsourced into a separate file.

In this context I ran into difficulties that I’ve managed to solve by guessing. But I still don’t understand why there is a difference with accessing the attributes and from where Nix/NixOS get the function attributes ({ lib, config, pkgs, ... }: and {config, home, ...}:) defined in the first row.

I’ve studied the Nix pills (up to chapter 5) and NixOS manual (chapter 5) - but still don’t get it.

Here is the minimized example of myuser.nix before refactoring:

{ lib, config, pkgs, ... }:

let 
  user = "myuser";
in
{
  imports =  [  <home-manager/nixos> ];

  users.users.${user}.isNormalUser = true;

  home-manager.users.${user} = { pkgs, ... }: {
  home = {
    username = user;
    homeDirectory = "/home/${user}";
    stateVersion = "23.05";
  };
  programs = {
    home-manager.enable = true;
    navi = {
      enable = true;
      settings.cheats.paths = [
         "${config.home-manager.users.${user}.xdg.dataHome}/navi/cheats/" 
      ];
    };
  };
}

The first thing I don’t understand at this point is why I have to access Home-Managers attribute xdg.dataHome by that ugly construct config.home-manager.users.${user}.xdg.dataHome.

Am I missing something and there is a more simplistic approach?
Or is it because xdg.dataHome is not set as attribute in this context because it will be set after the current file myuser.nix is evaluated later on? (my assumption)

Now I refactored the above example to this.
I sourced out the navi configuration into the file navi.nix.

myuser.nix is now

{ lib, config, pkgs, ... }:

let 
  user = "myuser";
in
{
  imports =  [  <home-manager/nixos> ];

  users.users.${user}.isNormalUser = true;

  home-manager.users.${user} = { pkgs, ... }: {
  home = {
    username = user;
    homeDirectory = "/home/${user}";
    stateVersion = "23.05";
  };

  imports = [ ./navi.nix ];

  programs = {
    home-manager.enable = true;
  };
}

navi.nix contains

{config, home, ...}:
{
  programs.navi = {
    enable = true;
    settings.cheats.paths = [
       "${config.xdg.dataHome}/navi/cheats/" 
    ];
  };
}

You may have noticed that I have replaced
config.home-manager.users.${user}.xdg.dataHome by ${config.xdg.dataHome}.

I’m a bit confused why this simplification is possible in the outsourced module only.
Furthermore I still don’t understand from where Nix retreives the attribute home in this file.
I read the Nix pills but still don’t understand.

Can somebody enlight me, please? :slight_smile:

Very briefly, all this magic comes from the “module system”, which is a small DSL written in the Nix language.

Currently the most useful piece of documentation to understand what’s going on is in the NixOS reference manual: NixOS 23.11 manual | Nix & NixOS

There are probably some useful or redundant bits in the user wiki: NixOS modules - NixOS Wiki

The documentation team has multiple efforts to better explain different aspects of the module system. Follow links from this GitHub issue for an incomplete list of unfinished collections of information: Using and documenting the module system outside NixOS · Issue #670 · NixOS/nix.dev · GitHub

1 Like