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
# 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
# Rollback to that channel version
$ sudo nix-channel --rollback 42

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)"


❯ 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


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
❯ cat /nix/var/nix/profiles/per-user/root/channels-*-link/nixos/svn-revision

How is this possible?

A month late, sorry, but: nothing stops you from GCing old profiles, including the channels profile used to build the current system. Your current system itself, and all of its transitive dependencies, are retained in the store during any GC operations, but the channel isn’t used at run time and the channel links live outside of the store. If you run nix-collect-garbage --delete-older-than 60d or nix-env --delete-generations 60d, and your running system is more than sixty days old, the channel link used to build the current system will get poofed and you’ll need to manually pin to whatever is in /run/current-system/nixos-version if you want to reproduce exactly the same system.

1 Like