How to pin nix registry nixpkgs to release channel

I had trouble working out how to pin the nixpkgs registry entry to a release channel. I’m posting it here in case anyone else finds it helpful.

On my system, I want the nixpkgs flake to refer to the nixos-21.05 channel (flake url: github:NixOS/nixpkgs/nixos-21.05). But I want this channel to be pinned to a known commit. I want to be able to update this manually.

In order to achieve this, I use the following steps:

  1. Starting off, I don’t have any user registry entries:

    $ nix registry list
    ....
    global flake:nixpkgs github:NixOS/nixpkgs
    ...
    

    At this point, the nixpkgs flake will refer to the master branch in github:NixOS/nixpkgs (which is currently immediately before the 21.11 release):

    $ nix eval nixpkgs#lib.version
    "21.11pre-git"
    
  2. First, you need to add an override to make nixpkgs refer to the nixos-21.05 branch:

    $ nix registry add nixpkgs github:NixOS/nixpkgs/nixos-21.05
    $ nix registry list
    user   flake:nixpkgs github:NixOS/nixpkgs/nixos-21.05
    ...    
    global flake:nixpkgs github:NixOS/nixpkgs
    ...
    
  3. You then need to pin github:NixOS/nixpkgs/nixos-21.05:

    $ nix registry pin github:NixOS/nixpkgs/nixos-21.05
    $ nix registry list
    user   flake:nixpkgs github:NixOS/nixpkgs/nixos-21.05
    user   github:NixOS/nixpkgs/nixos-21.05 github:NixOS/nixpkgs/1e5c35dfbc8e0ad8c35aa1a6446f442ca1ec5234
    ...
    global flake:nixpkgs github:NixOS/nixpkgs
    ...
    

    Now, the nixpkgs flake will refer to this known-good commit on the nixos-21.05 branch:

    $ nix eval nixpkgs#lib.version
    ""21.05pre-git""
    

When you want to bump the pin to the latest version of nixos-21.05, you can use the following command:

$ nix registry pin github:NixOS/nixpkgs/nixos-21.05

Note that you must not accidentally pin the nixpkgs flake. DO NOT DO THIS:

$ nix registry pin nixpkgs
$ nix registry list
user   github:NixOS/nixpkgs/nixos-21.05 github:NixOS/nixpkgs/1e5c35dfbc8e0ad8c35aa1a6446f442ca1ec5234
user   flake:nixpkgs github:NixOS/nixpkgs/9fcf2a8a2cb0f5b78edc8ec7ca877240e7fe3009
...
global flake:nixpkgs github:NixOS/nixpkgs
...
$ nix eval nixpkgs#lib.version
"21.11pre-git"

You can see that here the nixpkgs flake is now pointing back at the master branch. It is unfortunate that Nix doesn’t just “do the right thing” here.


When you want to make the nixpkgs flake point a more recent release of NixOS (the next version will probably be 21.11), you can use the following command:

$ nix registry add nixpkgs github:NixOS/nixpkgs/nixos-21.11
$ nix registry pin github:NixOS/nixpkgs/nixos-21.11
$ nix registry list
user   github:NixOS/nixpkgs/nixos-21.05 github:NixOS/nixpkgs/1e5c35dfbc8e0ad8c35aa1a6446f442ca1ec5234
user   flake:nixpkgs github:NixOS/nixpkgs/nixos-21.11
user   github:NixOS/nixpkgs/nixos-21.11 github:NixOS/nixpkgs/068984c00e0d4e54b6684d98f6ac47c92dcb642e
...
global flake:nixpkgs github:NixOS/nixpkgs
...
$ nix eval nixpkgs#lib.version
"21.11pre-git"

(Note that this won’t actually work until the nixos-21.11 branch has been created.)

7 Likes

You can also do a similar thing for other release channels / branches.

For instance, here is how to pin a flake pointing to the nixos-unstable channel:

$ nix registry add nixos-unstable github:NixOS/nixpkgs/nixos-unstable
$ nix registry list
user   flake:nixos-unstable github:NixOS/nixpkgs/nixos-unstable
...
$ nix registry pin github:NixOS/nixpkgs/nixos-unstable
$ nix registry list
user   flake:nixos-unstable github:NixOS/nixpkgs/nixos-unstable
user   github:NixOS/nixpkgs/nixos-unstable github:NixOS/nixpkgs/9bf75dd50b7b6d3ce6aaf6563db95f41438b9bdb
...

Now a command like nix shell nixos-unstable#xterm will pull xterm from nixos-unstable at commit 9bf75dd50b7b6d3ce6aaf6563db95f41438b9bdb.

I personally don’t like the global registry, with its imperative way of management.
Instead I remove the global registry and declaratively setup the user registry.

To remove the global registry, set the flake-registry option in nix.conf to an empty registry:

(an empty registry looks like: { "version": 2, "flakes": [] })

To configure the user registry, it is stored in ~/.config/nix/registry.json and I configure it with a home manager module of my own:

And I use it like this:

To declare a pkgs flake (pinned to the nixpkgs of my home flake) and an unstable user flake (on the github’s nixpkgs-unstable branch)

Hope it helps someone :slight_smile:

3 Likes

I autogenerate registry from flake inputs using this little module:

3 Likes

I think home-manager now has this as part of the nix module, see https://github.com/nix-community/home-manager/blob/0232fe1b75e6d7864fd82b5c72f6646f87838fc3/modules/misc/nix.nix

1 Like

@kouakitaki’s post makes the nixpkgs flake point to the same commit used to build the system, but it requires inputs, which in turn requires

  1. specialArgs = { inherit inputs; } in your nixpkgs.lib.nixosSystem call
  2. outputs = { self, nixpkgs, ... }@inputs: in your flake.nix

If your /etc/nixos only has configuration.nix and no flake.nix (like mine), you can make the nixpkgs flake point to the same commit used to build the system with

# /etc/nixos/configuration.nix
# { config, pkgs, ... }: {
  nix.registry.nixpkgs.to = { type = "path"; path = pkgs.path; };
# }

or if you’re still on NixOS 22.05 (like me)

  nix.registry.nixpkgs.to = { type = "path"; path = "${pkgs.path}"; };

This will add a system override for flake:nixpkgs pointing to your nixos channel:

$ nix registry list | grep flake:nixpkgs
system flake:nixpkgs path:/nix/store/wz4m5rihmc3wszckma7zd743bm4jaywx-nixos
global flake:nixpkgs github:NixOS/nixpkgs/nixpkgs-unstable

Now you can use nix shell nixpkgs\#foo -c (like nix run nixpkgs.foo -c before flakes) instead of nix-shell -p foo --run and get the same versions as the rest of your system!

3 Likes

I’ve done as you suggested and each call to nix run nixpkgs#xxx leads to a few second where nix copies / hash the path pkgs.path to the nix store.

Otherwise, using @koukitaki method, this does not happen.