Using the same `nixpkgs` version for flake-style `nix shell` and `home-manager`

Whenever I write nix shell nixpkgs#something, it usually downloads a new version of nixpkgs, which I find slightly annoying considering that I already have a downloaded version on my system via home-manager.

I have two questions:

  1. Is there a way to get nix shell to not download a new version of nixpkgs but use the currently cached one, presumably the one it used last time? By “version” I mean the choice of the commit in the nixpkgs repo.

    I tried the --no-update-lockfile option, but it didn’t work (I guess because nixpkgs is a “registry”? See below). --offline option seemed to do something similar to what I wanted, but it also led to building the packages being really slow (I guess it didn’t use some online binary cache), which I don’t want.

  2. Is there a way to get it to share the same version of nixpkgs as home-manager uses? This should allow it to re-use the same cache. I’m not sure whether this means reconfiguring home-manager, something else, or is just impossible currently.

Some details about my setup

I’m currently using Nix 2.24.6 on ARM Mac OS, installed recently with the Determenistic Installer.

I have home-manager installed as a flake, so its version of nixpkgs is recorded in ~/.config/home-manager/flake.lock on my system. I can’t tell where nix shell records its version of nixpkgs; files named flake-registry.json seem to be involved in that.

I’m not an expert on flakes (in case you couldn’t tell :slight_smile: ), I’m mainly using them because the Deterministic Nix installer makes it easier to use them than not.

{ inputs, ...}:
{
  nix.registry.nixpkgs.flake = inputs.nixpkgs;
}

assuming you passed the flake inputs into the module system by setting inputs in extraSpecialArgs

Thank you, but I’m a bit confused. Where would this go? Or did you switch the two and are saying that I can put

inputs.nixpkgs = nix.registry.nixpkgs.flake;

inside ~/.config/home-manager/flake.nix? This didn’t work for me with the error “undefined variable ‘nix’”.

To be clear, I’m running nix shell nixpkgs#something in an arbitrary directory, not necessarily inside a flake. I suppose I could put a flake.nix in my $HOME, but this seems risky.

In your HM config. It’s to configure the nixpkgs flake registry entry for your user.
And in turn, when you use nixpkgs#foobar, that references the nixpkgs registry entry.

And how would I do this? I tried a few things, but nothing worked immediately.

For reference, here’s my home-manager flake.nix. You’ll see I did something a little similar before, but I couldn’t pass inputs on in the same way.

# To load:
# nix run home-manager/master --impure -- switch --impure
{
  description = "Home Manager configuration of ilyagr";

  inputs = {    
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    nixpkgs2311.url = "github:NixOS/nixpkgs/c8e74c2f83fe12b4e5a8bd1abbc090575b0f7611";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, nixpkgs2311, home-manager, ... }:
    let
      system = "aarch64-darwin";
      pkgs = nixpkgs.legacyPackages.${system};
      pkgs2311 = nixpkgs2311.legacyPackages.${system};
    in {
      homeConfigurations."ilyagr" = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        modules = [ ~/.config/home-manager/home.nix ];

        # Needed to pass through extra arguments to home.nix
        extraSpecialArgs = { inherit pkgs2311; };
      };
    };
}

Change ~/.config/home-manager/home.nix to ./home.nix, stop using --impure, and to answer your question, you need to pass inputs into the module system as so:

outputs = { nixpkgs, nixpkgs2311, home-manager, ... } @ inputs:

Then extraSpecialArgs = { inherit inputs; }; would work, allowing you to use inputs.whatever in your modules.

Thank you very much! This seems to work well (though I haven’t played around with it that much). For other people’s reference, here’s what I did. (flake.mac.template.nix should be flake.nix, I left it as is for the purposes of another comment I’m planning to write):

diff --git a/.config/home-manager/flake.mac.template.nix b/.config/home-manager/flake.mac.template.nix
index ff83a96..a5459ca 100644
--- a/.config/home-manager/flake.mac.template.nix
+++ b/.config/home-manager/flake.mac.template.nix
@@ -17,7 +17,7 @@
     };
   };
 
-  outputs = { nixpkgs, nixpkgs2311, home-manager, ... }:
+  outputs = { nixpkgs, nixpkgs2311, home-manager, ... } @ inputs:
     let
       system = "aarch64-darwin";
       pkgs = nixpkgs.legacyPackages.${system};
@@ -31,7 +31,7 @@
         modules = [ ~/.config/home-manager/home.nix ];
 
         # Needed to pass through extra arguments to home.nix
-        extraSpecialArgs = { inherit pkgs2311; };
+        extraSpecialArgs = { inherit pkgs2311; inherit inputs; };
       };
     };
 }
diff --git a/.config/home-manager/home.nix b/.config/home-manager/home.nix
index 4c6e91f..ef64bba 100644
--- a/.config/home-manager/home.nix
+++ b/.config/home-manager/home.nix
@@ -1,4 +1,4 @@
-{  config, pkgs, pkgs2311, ... }:
+{ inputs, config, pkgs, pkgs2311, ... }:
 
 {
   # Home Manager needs a bit of information about you and the paths it should
@@ -17,7 +17,7 @@
   nix.package = pkgs.nixVersions.nix_2_21;
 
+   # https://discourse.nixos.org/t/using-the-same-nixpkgs-version-for-flake-style-nix-shell-and-home-manager/52243/2
+  nix.registry.nixpkgs.flake = inputs.nixpkgs;
+ 
   # The home.packages option allows you to install Nix packages into your
   # environment.

The effect of this on my system is that home-manager creates a symlink ~/.config/nix/registry.json that fixes the nixpkgs version to a commit.

I wish it were a bit easier (I guess it’d have to be a change to home-manager’s default config), but I’m quite grateful it’s possible.

Now, in case you are interested, to reply to your other points:

The reason I’m using impure is because I want to store this config inside my dotfiles repo. I use stow, so home.nix is actually a symlink to ~/stow/mac_config/.config/home-manager/home.nix, where ~/stow/mac_config is one of my dotfile Git repos. This does not work without --impure.

I also very much wish flake.nix was also a symlink, but that doesn’t work even with --impure. So, flake.nix is just a file, and I keep copying its contents manually to ~/stow/mac_config/.config/home-manager/flake.mac.template.nix. Fortunately, it changes rarely.

The two simplest alternatives that might work would be to use some approach to dotfiles, e.g. a dotfile manager like chezmoi that doesn’t use symlinks, and/or to keep Home-Manager config in a git submodule of my main config (since flake.nix seems to be meant to be in the root of a Git repo). Both seem like too much hassle, Nix is not so central to my life that I want to rethink my dotfile setup just for it (and I don’t want to put all of my dotfile config inside home-manager for similar reasons).

Do you have a better suggestion?

Change ~/.config/home-manager/home.nix to ./home.nix,

Perhaps this is your better suggestion, but I did not understand it.