How do the `imports = [...];` in home manager work? Where do arguments to imported functions come from?

Hello. I pinned nixpkgs in home manager and I want to use imports like in the following example to break configuration down into manageable pieces. I can’t find docs on how it works exactly.

Do the arguments to functions { config, pkgs, ... }: in the imported files come from channels? Or from files that imported them?

##### home.nix #####

# The pkgs var that come from channels is overshadowed
# and essentially discarded in the let closure.
{ config, pkgs, ... }:
let
  pkgs = import (builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/bca9437d1eae9519b61a58f2593f25f65494f8e9.tar.gz";
  }) {};
in
{
  imports = [ ./emacs.nix ];
  
  # ...
}

##### emacs.nix #####
 
# Where does the pkgs var come from: from the let closure above?
# Or from channels?
{ config, pkgs, ... }:     
in
{
  home.packages = [
    pkgs.emacs
  ];
}

Should I copy the let closure to all imported files?

Or maybe I should do something like this?

imports = [ (import ./emacs.nix {inherit pkgs config;}) ];

The imports are resolved by nixpkgs.lib.evalModules. There is a little documentation for it here Nixpkgs Reference Manual

1 Like

Thanks. There’s a comment in the referenced modules.nix file:

Submodules do not inherit args from their parent module, nor do they provide args to their parent module or sibling submodules.

This means that I have to pass the overshadowing pkgs variable everywhere.

Adding the let in all imported files is not that bad though, because I’m using npins, it will take care of passing the right value everywhere.

##### all .nix files, including home.nix and emacs.nix #####
{ config, pkgs, lib, ... }:
let
  sources = import ./npins;
  pkgs = import sources."nixpkgs" {};
in
{
  # ...
}

This answers my question.

But what about the following? I’m new to nix, and I’d like to know if this is an ok way for the purpose.

imports = [ (import ./emacs.nix {inherit pkgs config;}) ];

Haven’t really seen anyone use home-manager with npins. Home-manager endorses flakes for pinning nixpkgs.

Well, I use home manager with npins after reading the following blog post.

Any downsides to anticipate?

Did you set the registry and nix path entries like the blogpost mentioned? That’s the most crucial part.

PS: HM was not designed well wrt flakes, I would even say hm+flakes is broken.

No, I don’t use nixos yet, I use debian, at this point nix is enough for me.

Could you clarify? I’m new to nix, I don’t understand what’s wrong with hm+npins.

Ah, sorry, I misread your message when I was writing my previous message. You wrote “hm+flakes is broken” not “hm+npins is broken”. Hm. This means I should stick with npins then.

The blogpost already explains how to set NIX_PATH correctly. Your let expression will cause problems because there’s a mismatch between pkgs the module arg and what you want to use as your nixpkgs instance, because things like programs.whatever.enable will still use the module arg’s value.

Oh, I now get it. Do you mean this line from the “killing channels” section?

Let’s fix the NIX_PATH. Add this module worth of code into your config somewhere, say, pinning.nix, then add it to imports of configuration.nix:

But I should use home.nix instead of configuration.nix, as I don’t use nixos, right?

Yeah, luckily, the settings for nix have the same structure in NixOS and HM.

1 Like

Great, thank you. I would totally miss the importance of this.

@waffle8946, what do you think about the approach in this config? It’s close to what’s described in the blog post, yet different, and to me, it’s much simpler. It seems it can be adopted to be used with home-manager.

Yes, there’s multiple (though ultimately similar) approaches to this. sanix is doing the same thing (setting nix.path to affect NIX_PATH) but instead of an indirection via the flake registry it’s just using pkgs.path directly.

1 Like

Oh I thought you’d need to doubly rebuild w/ sanix but it seems like that’s addressed via this script:

Of course you’ll have to tweak nixpkgs/path.nix slightly for npins.

That’s similar to jade’s script under “Fixing the UX issues”, which achieves the same effect. Doesn’t seem like sanix is simpler, the complexity appears to be similar.

Yeah, not simpler, but easier to me personally, because I’m not familiar with flakes at all.

Do I understand correctly that in my case I should mostly replace the very last line in the script and use something like this? And remove all mentions of nixos-config, because they are not needed?

exec home-manager "$@" -I nixpkgs="$nixpkgsPath"

I mean, besides removing channels and other steps.

Should work, though depending on where your hm config is located, you’ll also want to add -I home-manager="/path/to/your/hm/config.nix" to that command

1 Like

Hello. Could you help me?

I’d like to set nix.nixPath just like in the sanix example.

# Makes commands default to the same Nixpkgs, config, overlays and NixOS configuration
  nix.nixPath = [
    "nixpkgs=${pkgs.path}"
    "nixos-config=${toString ./root.nix}"
    "nixpkgs-overlays=${toString ./nixpkgs/overlays.nix}"
  ];

But the nix.nixPath only exists in the home-manager unstable, not in 24.05, nor any other:

https://home-manager-options.extranix.com/?query=nix.nixPath&release=master

Is the following enough?

I found the following in the source code of home-manager:

https://github.com/nix-community/home-manager/blob/8cf9cb2ee78aa129e5b8220135a511a2be254c0c/modules/misc/nix.nix#L279

home.sessionVariables.NIX_PATH = "${nixPath}";

I mean, the build script works, when I manually copy this line instead of trying to use nix.nixPath.

$NIX_PATH seems to be in effect, not ignored at all:

$ NIX_PATH=foo=$HOME nix-instantiate '<foo>' --eval --expr
/home/alejandro

And <nixpkgs> matches $NIX_PATH:

$ echo $NIX_PATH 
nixpkgs=/nix/store/mvrc9p3hfp7dcjnxl1chb4vrnjm4qs3z-26fz3a49sb9n58cdc5bgsgs1njy72vy1-source:nixpkgs-overlays=/home/alejandro/wo/.setuplets/home-manager/nixpkgs-overlays.nix
$
$ nix-instantiate '<nixpkgs>' --eval --expr
/nix/store/mvrc9p3hfp7dcjnxl1chb4vrnjm4qs3z-26fz3a49sb9n58cdc5bgsgs1njy72vy1-source