rhelmot blog

A beginner's guide to NixOS channels vs flakes

The goal here is to answer the question “how does your system know what version of nixpkgs to use”, i.e. “how do you tell what version of firefox I am going to get when I ask for firefox to be installed”.

There are two approaches, channels and flakes. The long and the short of this is that channels are a mechanism baked into your system1 and flakes are a mechanism stored in a file next to your configuration.

I do not know of a version of managing either of these that doesn’t involve using the terminal the entire time.

Channels

To manage channels, you will use the nix-channel command in the terminal. You will need to run it as the root (administrator) user, i.e. prefix the command with sudo. This can be confusing because if you run nix-channel as your non-privileged user, i.e. the default when you don’t prefix with sudo, it will still do something, but that something will almost certainly not be what you want!

Start with sudo nix-channel --list. This will list all the channels that are being managed by your system. Usually there is just one, named “nixos”. You can see that it probably points at something like https://nixos.org/channels/nixos-25.05.

If NixOS 25.11 were to come out tomorrow, you would just change the 25.05 to 25.11 and you would get all the shiny new software. You can do this with sudo nix-channel --add https://nixos.org/channels/nixos-25.11 nixos.

If you simply want to do a light upgrade and get only the software vetted for the 25.05 release but with any important fixes that have been discovered since release, you just want sudo nix-channel --update nixos. This will check if there is a new version of 25.05 available and switch to it if there is. Weird that even though there’s a version number, there’s subversions of that version…

Flakes

Flakes are the alternative which doesn’t bake anything into your system, and are in fact philosophically designed to avoid having to bake anything into your system. The “goal” per se is to make it so that you can share a folder of files and suddenly your system is fully 100% reproducable, locking in place the version of nixpkgs (and potentially more things!) in a way that is simply just in a text file and is easily sharable.

These text files are named flake.nix and flake.lock. flake.nix is a file that you can edit, technically in the same language as your configuration.nix file but using some more arcane features. flake.lock is still a text file but you are not meant to edit it by hand. Instead, you run the nix flake update command, and the flake.lock file is automatically regenerated with the newest version of everything.

Writing a flake.nix file is a little weird, you would probably just want to copy one from someone else online. Maybe start with 2 I don’t think I can explain how to write one from first principles in just this document. However, once you find one, it will also contain a line which basically says “nixpkgs is going to be a version named 25.05”. If you edit this file to say 25.11, your next system build will use 25.11.

One of the other benefits of using flakes is that you can put your configuration.nix and hardware-configuration.nix files anywhere, not just in /etc/nixos. You will have to put them in the same folder of flake.nix and flake.lock (or in a folder next to those files), but you can put the folder containing all that crap literally wherever.

One final caveat is that if you have a git repository that contains your flake files, nix will ignore files which are in that folder but not tracked by git. This doesn’t matter unless you start using git on the command line :)

A table comparing terminal commands

Goal Channels solution Flakes solution
Switch to the most recent release of your current version of nixos sudo nix-channel --update nixos nix flake update (Automatically edits flake.lock)
Switch to a different release version of nixos sudo nix-channel add ... nixos Edit flake.nix
Build a configuration and make your system use it sudo nixos-rebuild switch3 sudo nixos-rebuild switch --flake path/to/folder-that-has-flake-stuff

The dirty details

The nix programming language has a weird escape hatch for accessing external resources at evaluation time. If you ever see nix code that looks like with import <nixpkgs> {}; blah blah, this is using this escape hatch! This syntax, the import with angle brackets, refers to an “impure” resource, i.e, some sort of external truth which dictates what code you actually mean by nixpkgs. This is widely considered to be a bit of a wart on the language’s beautiful face! People love nix for its purity (technical term) and its reproducability, and this capability shoots that down immediately. Flakes are designed to be the solution to this - the angle brackets import syntax simply will not work in the “pure” evaluation mode, which is used when working with flakes. Instead, the nix interpreter understands the special structure of the flake.nix and flake.lock files and reads these in order to populate a list of inputs, which it provides to code running in the flake.nix file (outputs). In this guide, nixpkgs has been the only input, but you can use lots of other things as inputs! Random github repositories that have a flake.nix if you like!

The flake.nix structure is actually a very extensible structure that can be used for lots of things other than a NixOS system configuration. Take a look at 4 for all the things that can be done :)


  1. Associated with the root account, in /nix/var/nix/profiles/per–user/root/channels  ↩︎

  2. https://wiki.nixos.org/wiki/NixOS_system_configuration#Defining_NixOS_as_a_flake  ↩︎

  3. This will by default use /etc/nix/configuration.nix  ↩︎

  4. https://wiki.nixos.org/wiki/Flakes  ↩︎