I’ve managed to glean the following information about the various Nix channels. I haven’t found these facts in one place, so I’m posting them here. Please correct me for any inaccuracies.
nixos-xx.yy, the ‘LTS’ channels, denoted by version number
nixos-unstable the rolling-update unstable NixOS
nixpkgs-unstable, recommended for Nix-as-a-package-manager (NaaPM)
nixos-(xx.yy|unstable)-small, a subset of NixOS curated for minimal servers.
Despite all the docs advising nixos-* for NixOS and nixpkgs-* for NaaPM, there is theoretically nothing that prevents you from using nixos-* for NaaPM and nixpkgs-* for NixOS. It is merely assumed that NaaPM users already have a stable system and want cutting-edge packages, whilst NixOS users need to rely on a more stable set. Beware, however, that something may break, because maintainers will assume this convention is followed.
nixpkgs-unstable is a statement of fact rather than a variant - there is no nixpkgs-stable (except maybe for Darwin?)
The set of packages in nixpkgs-unstable is not related in any way to nixos-unstable. nixos-unstable is only slighty less stable than nixos-stable (and is intended for rolling updates), nixpkgs-unstable is quite a bit looser.
All three of them are based on the nixpkgs master branch. Each of them advance only if all of their tests are passing. The only difference is the list of tests that each of them have.
It seems that nixos-* runs a ‘tighter’ set of packages - different packages are more likely to depend on the same version of a dependency, so you’ll have less duplicate packages in /nix/store.
nixpkgs-* contains a lot of macOS (Darwin)- specific packages, which nixos-*, being Linux-based, doesn’t need.
Besides for the above points, and of course package versions, it seems there are very few (no?) packages available on nixpkgs which aren’t on nixos-*.
One takeaway is, if you’re running NaaPM on Linux and can survive not having the latest version of everything, subscribing to nixos-unstable instead of nixpkgs can save you some disk space.
All the “unstable” channels are a snapshot of master branch at a certain point of time, all the “stable” channels are a snapshot of release-*.* branch. (Think git tags that move along the respective branches.) The difference is how often they advance, or rather what are the criteria for their advancement (tests that need to succeed).
The nixos channel also runs many more nixosTests as part of it jobset as well as constituents (required jobs for a channel release). And the nixos channel is the one which also creates the command database which is used for the command-not-found logic:
[09:15:16] jon@jon-desktop /home/jon/projects/nixpkgs (master)
$ kubectl
The program 'kubectl' is not in your PATH. It is provided by several packages.
You can make it available in an ephemeral shell by typing one of the following:
nix-shell -p kubectl
nix-shell -p kubernetes
nix-shell -p openshift
The site also had this very nice description of the update process by @domenkozar, which is why I continued linking it even after it stopped updating. But I guess I can just quote it here:
How does channel update?
1. Git commit
Anyone with commit access can push changes to either master or one of the release-XX.XX branches.
2. Hydra build
Each channel has an associated jobset on Hydra (Nix CI) that is a collection of individual jobs . A job roughly corresponds to building a particular package, which itself may depend on other packages built by other jobs .
Before a channel can update, its associated jobset must be finished building, though the building of some jobs may fail.
As long as certain special jobs – unstable for nixpkgs, and tested for nixos – build successfully, the channel can update. The role of these special jobs is to ensure that essential functionality is present on each channel update.
There are two major differences between those jobsets:
nixpkgs-unstable
builds all packages for supported platforms (Linux, Darwin)
unstable job that consists of most commonly used packages
nixos-*
builds all packages and NixOS machinery only for Linux
tested job that consists of mostly NixOS tests firing up qemu instances with different kinds of configurations
3. Channel update
For a channel to be updated two conditions need to be satisfied:
Particular jobset evaluation needs to be completely built ie. no more queued jobs, even if some jobs may fail
Particular jobset evaluation’s tested/unstable job needs to be built succesfully
The nixos.org server has a cronjob for which nixos-channel-scripts are executed and poll for the newest jobset that satisfies the above two conditions and trigger a channel update.
Once triggered, release files such as ISOs are copied. For the NixOS channel command-not-found index is generated, which can take some time since it has to fetch all packages.
nixpkgs is quickly updated since none of the above needs to happen once a channel update is triggered.
Some details are no longer true (e.g. the command-not-found tooling has been replaced by nix-index) but I believe it is still mostly correct.
No, if you want to use a stable release, its always containing the xx.yy in its name.
Upgrading from one stable release to the next is always a breaking change, so you don’t want to do that indirect for any manner of stability.
Just the unstable branch (so the newest thingy) has a channel name that is continuous (nixos-unstable).
That might be, but still the command to add the currently latest stable channel (which actually renders to xx.yy) would be handy, especially for scripts.
For a script you will not need a channel to find the latest stable.
The Prometheus instance knows all channel states, that could be queried for the needed information (if not queried irresponsible)
so something like that (hacked together without super fluent in jq) would totally do the job for a script without creating extra channels.
Possibly there is even another source for that info.
The only situation where i am not 100% sure is, what the result is here, when there are 2 actively maintained stable channels (which is the situation for one month after a release), but i am quite sure it will be a situation that can be handled for a script to choose one of both.
Yes. And why wouldn’t it be? A stable branch should be stable, and a jump between stable versions should require an explicit invocation to opt into the new stable version, because you’re getting 6 months of breaking changes in one go.
There’s no guarantee that code you wrote for release X will work for release X+1, so you explicitly state which release your code is targeted for.
I even don’t see that we are special here. For Debian 12 upgrade (and other apt based distros) one need to replace the magic word bullseye with bookworm (for Debian) in some specific files that differ between setups (depending on how I configure apt).
I bet the system for rpm flavoured is quite the same.
The difference that I see here is that we don’t hide version numbers behind magic code words for the versions.
Tooling wise it’s a similar mess than for other non rollers, that the process where to change differs on what is used (channels, npin, flakes etc).
So I don’t see that we are super wired here, but maybe I am missing something.