How to use a nixpkgs clone as nixos channel?

I would like to switch from

$ sudo nix-channel --list
nixos https://nixos.org/channels/nixos-20.03

to using a cloned nixpkgs git repo as my nixos channel.

This is mainly because the channel workflow makes some things problematic:

  • After I sudo nix-channel --update and start nixos-rebuild boot, I sometimes notice that now I don’t have the time to finish the upgrade. So I Ctrl-C it. But then my channel is already changed, and I can no longer edit configuration.nix and apply some simple, instantaneous changes, because any subsequent nixos-rebuild switch will use the updated channel and thus take a long time. Channels do not seem to have local history, so I cannot undo my nix-channel --update if I did not write down what the previous version was.
  • I would like to keep track of all NixOS versions I ever ran, even past GC. A git reflog would make that every easy.

Unfortunately, I cannot seem to add a directory as a channel:

$ sudo nix-channel --add /etc/nixos/nixpkgs nixos
error: invalid channel URL '/etc/nixos/nixpkgs'
$ sudo nix-channel --add file:///etc/nixos/nixpkgs nixos
$ sudo nix-channel --update
error: unable to download 'file:///etc/nixos/nixpkgs/nixexprs.tar.bz2': Couldn't read a file:// file (37)

importing a specific revision inside configuration.nix is also not a good option for me, because it seems configuration.nix is just a nixos module (loaded from where?) and it does not even refer to the <nixos> import, so that probably is not as complete as changing the channel.

I could write NIX_PATH=... in front of every command I run, but that is easy to forget.

How can I use a directory as the nixos channel?

I guess this part I can answer now:

[root@t25:~]# echo $NIX_PATH
/root/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
  • nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos makes that the nixos channel provides the <nixpkgs> variable.
  • nixos-config=/etc/nixos/configuration.nix sets the nixos-config variable, which is read somewhere from within nixpkgs.

The main question still remains.

nix-channel doesn’t have any kind of support for this that I know of. You’ll need to use -I nixpkgs=./nixpkgs on the command line (I use a wrapper script for this), and you’ll probably want to set nix.nixPath = ["nixpkgs=${./nixpkgs}"]; in your config. Interestingly, this combination will make every generation’s NIX_PATH point <nixpkgs> to the exact version of nixpkgs that the generation was built with. Personally I rather like that.

2 Likes

It does seem like nix-channel supports rollbacks: Introduction - Nix Reference Manual

1 Like

import ing a specific revision inside configuration.nix is also not a good option for me, because it seems configuration.nix is just a nixos module (loaded from where?) and it does not even refer to the <nixos> import, so that probably is not as complete as changing the channel.

I realize you might be looking to keep channels around, but I had the exact same issues with them as you do and tried this: Specifying unstable commit directly in configuration.nix - #2 by JohnAZoidberg

That is, in configuration.nix, I pinned the nixpkgs repo and set the nixpkgs reference in NIX_PATH to point to that version. This way it’s declarative (rollbacks and all) and I could remove all channels for the root user. I also cleared the channel list for my own user, and do nix-env -f '<nixpkgs>' for user environment stuff. As stated in the post, the only caveat is that when changing the nixpkgs version, I need to rebuild twice (or supply a -I nixpkgs=...), since NIX_PATH is set as a result of evaluating configuration.nix (and not the other way around, I assume).

Just tried it out the other day and no problems so far. If there’s a better way go about this I’d love to hear about it. In the long run I think Nix flakes was made for addressing these things.

You are right!

% ls -lah /nix/var/nix/profiles/per-user/niklas/
total 108K
drwxr-xr-x 3 niklas niklas 4.0K Aug 20 14:06 ./
drwxr-xr-x 4 niklas niklas 4.0K Jun  2  2018 ../
lrwxrwxrwx 1 niklas niklas   16 Aug 20 14:06 channels -> channels-66-link/
lrwxrwxrwx 1 niklas niklas   60 Jan 25  2020 channels-62-link -> /nix/store/fp5y3zvvi9mh8cg6v1qmcrsrc05lsc2s-user-environment/
lrwxrwxrwx 1 niklas niklas   60 Jun 20 17:18 channels-63-link -> /nix/store/vr9k7rzkwmdf1nl5jhx2fl46pcqlad28-user-environment/
lrwxrwxrwx 1 niklas niklas   60 Jun 20 17:18 channels-64-link -> /nix/store/cn4zpadckzv6gska3a9psxc71y144xlp-user-environment/

This addresses the

Channels do not seem to have local history

part.

you could also use niv inside of a personal git repo.

Git would version control what all of your dependencies are, and then you can use niv to easily update source locationos.