How to roll back channel to currently active version?

The latest sudo nixos-rebuild boot --upgrade-all run failed because of a broken package. How do I revert the relevant channel to the version which was used to build the currently running system?

This is not the same as Rolling back a channel, because sudo /run/current-system/bin/switch-to-configuration boot did not result in sudo nixos-rebuild switch working.

# Get the currently running system's version number
$ cat /run/current-system/nixos-version
23.11.5353.878ef7d9721b
# Ignore the first two numbers, and find the
# channel link matching the rest
$ for c in /nix/var/nix/profiles/per-user/root/channels-*-link; do
>   fgrep -q .5353.878ef7d9721b $c/nixos/svn-revision && echo $c
> done
/nix/var/nix/profiles/per-user/root/channels-42-link
# Rollback to that channel version
$ sudo nix-channel --rollback 42
2 Likes

Nice! I’ve chucked it all together into a one-liner:

sudo nix-channel --rollback "$(grep --fixed-strings --files-with-matches "$(cut --delimiter=. --fields=3 /run/current-system/nixos-version)" /nix/var/nix/profiles/per-user/root/channels-*-link/nixos/svn-revision | tail --lines=1 | cut --delimiter=- --fields=3)"

Verified:

❯ sudo nixos-rebuild boot --show-trace --upgrade-all # fails
❯ sudo nix-channel --rollback "$(grep --fixed-strings --files-with-matches "$(cut --delimiter=. --fields=3 /run/current-system/nixos-version)" /nix/var/nix/profiles/per-user/root/channels-*-link/nixos/svn-revision | tail --lines=1 | cut --delimiter=- --fields=3)"
switching profile from version 45 to 43
❯ sudo nixos-rebuild switch # succeeds

:heart:

1 Like

It probably is worth mentioning that these sorts of problems are inherent to channels, as they are global mutable state.

So a more principled fix here is to avoid using channels, and instead specify the exact hash of nixpkgs you depend on as a part of your configuration.

However, there’s no community consensus on how exactly to do that: there flakes, niv, and various tricks on how to do it yourself.

Of the top of my head, I don’t know a good guide surveying all the different ways to explicitly pin dependencies. I personally use flakes, though “use” would be a bit of an overstatement :slight_smile:

Yeah, I don’t know why so many people recommend not using channels when they are the only currently workable solution to have an evolving system.

To me this seems pretty clear:

  • non-reproducibility/non-hermiticity of channels is a huge drawback, and it goes directly against the core value proposition of nix (reproducible configurations)
  • there are workable alternatives! While it is true that the community is continually failing to converge on a single solution, any existing solutions work.

In particular, flakes or niv give you the same evolvability experience as channels, in that you run upgrade command and get new version of nixpkgs. The difference is that the specific version gets recorded with your configuration, so rollbacks work as expected. This is a major benefit, and, for me personally, outweighs the drawback of somewhat less polished and less “central” ux.

1 Like

I’ve run into a situation where there is no channel link matching the current system version:

❯ cat /run/current-system/nixos-version
24.05pre608655.ff0dbd94265a
❯ cat /nix/var/nix/profiles/per-user/root/channels-*-link/nixos/svn-revision
609462.4cba8b53da47

How is this possible?