Upgrades¶
Overview¶
Keep NixOS current by refreshing the expression source you track, then rebuilding. The workflow splits on how /etc/nixos is wired:
- Channel hosts: refresh root’s
nixoschannel, then rebuild (nixos-rebuild switch --upgrade, ornix-channel --updateplusnixos-rebuild switch). - Flake hosts: bump pins in
flake.lock(nix flake updateor a single input), then rebuild with--flake.
Channels ship Nix expressions plus pre-built binaries; which channel you subscribe to controls how aggressive updates are. Stable lines (nixos-YY.MM, e.g. the current stable on channels.nixos.org) take conservative bug fixes and package bumps. nixos-unstable follows main development and is not recommended for production (NixOS manual — Upgrading). *-small variants of either carry fewer binary packages: they advance faster but often need more local builds—mainly for servers.
A first install subscribes root to the channel matching the install media. Upgrading packages and the OS does not mean bumping system.stateVersion—leave that alone unless you have audited migrations. Choosing switch vs boot is a separate decision from the channel/flake refresh.
Details¶
Channel or flake: pick your upgrade path¶
| Host type | Refresh step | Rebuild step |
|---|---|---|
| Channel | nix-channel --update nixos (or nixos-rebuild … --upgrade) |
nixos-rebuild switch |
| Flake | nix flake update (or update one input) |
nixos-rebuild switch --flake .#hostname |
Channel-based systems read nixpkgs from root’s nixos channel subscription. Flake-based systems ignore that channel for the system configuration; pinned inputs live in flake.lock. See channel (concept) and flake (concept).
Channel hosts¶
Channel kinds¶
| Kind | Example name | Role |
|---|---|---|
| Stable | nixos-YY.MM |
Conservative updates; maintained until the next stable branch |
| Unstable | nixos-unstable |
Main development branch; radical changes possible |
| Small | nixos-YY.MM-small, nixos-unstable-small |
Same sources as above, fewer binaries, faster channel bumps |
Browse live channel URLs at channels.nixos.org. Unreleased lines may appear there during a release cycle; use the download page for the newest supported stable.
Inspect and switch (as root)¶
System rebuilds use root’s channel list. List the NixOS subscription:
Switch channel (the subscription name must be nixos):
# as root — replace YY.MM with the current stable, e.g. 26.05
nix-channel --add https://channels.nixos.org/nixos-YY.MM nixos
Examples: nixos-YY.MM-small for a leaner server channel, or nixos-unstable for the bleeding edge.
Per-user channels. nix-channel is per user. Adding or updating a channel as a non-root user does not change what /etc/nixos rebuilds see. Run channel commands as root (or with sudo) for system upgrades.
Channel-based upgrade¶
Usual one-liner:
That is equivalent to:
Rebuild modes (switch, boot, test) are covered in rebuild / switch / boot / test. After a bad upgrade, use rollbacks; for build failures see troubleshooting.
Flake hosts¶
Flake hosts do not rely on root’s nixos channel for the system flake. Refresh pinned inputs in flake.lock, then rebuild:
# in the flake directory (often /etc/nixos)
nix flake update
sudo nixos-rebuild switch --flake .#hostname
Update one input only (e.g. nixpkgs):
nix flake update is experimental CLI (nix-command + flakes; see nix.dev). Replace .#hostname with your flake output. Concept and lockfile behavior: flake, lockfile. Moving off channels: migration from channels.
Apply: switch vs boot¶
Refreshing the channel or lockfile only changes which expressions you build. How you apply the new generation still follows rebuild actions:
| Goal | Command (after refresh) |
|---|---|
| Activate now and set boot default | nixos-rebuild switch (channel: often via --upgrade) |
| Set boot default only; activate on next reboot | nixos-rebuild boot |
| Try now without changing the boot default | nixos-rebuild test |
Prefer boot (then reboot) when you want kernel/initrd changes deferred to the next boot, or when mid-session activation is undesirable. Prefer test for a risky upgrade you may abandon by rebooting. system.autoUpgrade.operation can be "switch" or "boot" for the same reason (option search).
Specialisations (cousin, not a pin bump)¶
Specialisations are extra system closures built with the parent generation. An upgrade that rebuilds the host rebuilds those children too; it does not replace channel/flake.lock refresh. After the new generation is active, switch into a named specialisation with nixos-rebuild … --specialisation name (or the child’s switch-to-configuration) when you need that variant—not as a substitute for updating nixpkgs.
Schema / downgrade warning¶
Moving between channels is usually fine. Exception: a newer NixOS may ship a newer Nix that upgrades the Nix database schema. That change is hard to undo, so you may be unable to return to the older channel afterward (NixOS manual — Upgrading).
Automatic upgrades (system.autoUpgrade)¶
Set options in configuration.nix. system.autoUpgrade.enable = true starts a periodic nixos-upgrade.service (check schedule with systemctl list-timers).
Channel path (default). With no flake set, the service runs the equivalent of nixos-rebuild <operation> --upgrade (plus module defaults). Optional explicit channel URI:
{
system.autoUpgrade.enable = true;
system.autoUpgrade.channel = "https://channels.nixos.org/nixos-YY.MM";
system.autoUpgrade.allowReboot = true; # optional
}
When channel is unset, the module uses root’s existing nix-channel subscription.
Flake path. Point at a flake URI instead of a channel—the two options cannot both be set:
{
system.autoUpgrade.enable = true;
system.autoUpgrade.flake = "github:owner/repo#hostname";
system.autoUpgrade.upgrade = false; # honour lockfile; see below
}
With flake set, the service passes --refresh --flake <uri> to nixos-rebuild. Other useful options:
| Option | Default | Role |
|---|---|---|
system.autoUpgrade.upgrade |
true |
When channel is null, also pass --upgrade. Set false on flake hosts to rebuild from the pinned lockfile without that flag. |
system.autoUpgrade.operation |
"switch" |
"switch" or "boot". |
system.autoUpgrade.dates |
"04:40" |
systemd calendar for the timer (systemd.time(7)). |
system.autoUpgrade.allowReboot |
false |
Reboot when the new generation changes kernel, initrd, or kernel modules. |
Lockfile vs auto-upgrade. Automatic rebuilds use whatever revision the flake URI resolves to—typically the lockfile in that repo. Refreshing inputs (nix flake update) is a separate step: run it (or a dedicated oneshot) before the timer fires, commit the updated flake.lock, and let the next scheduled rebuild pick it up. system.autoUpgrade.flags can pass extra nixos-rebuild arguments, but using deprecated --update-input / --recreate-lock-file there is easy to get wrong; prefer explicit nix flake update plus rebuild, or a separate automation for lockfile bumps.
system.stateVersion¶
system.stateVersion records the first NixOS release this machine was installed with, so modules can keep defaults compatible with on-disk state (databases, data dirs, and similar). It is not the channel or flake revision you are running (system.stateVersion option; also asserted in nixpkgs version.nix).
- Most users should never change it after the initial install—even when moving to a newer
nixos-YY.MMchannel or updating flake inputs. - Changing it does not upgrade packages or the OS; a lower value does not mean the system is outdated or unsupported.
- To switch releases or unstable, change only the channel and/or flake input URLs—do not touch
stateVersionas an “upgrade” lever. - Bump only after you have manually inspected every module effect that depends on it and migrated stateful data accordingly.
Set it once at install to the release you started on (e.g. "26.05"). Leave it alone through routine upgrades.
Boundaries (what this page is not)¶
- Rollback procedures—selecting a previous generation at boot.
- Flake schema—
flake.nixoutputs and evaluation layout. - nixpkgs packaging—adding or overriding packages.
Examples¶
Channel host: list root’s NixOS channel, switch to current stable, and upgrade:
sudo nix-channel --list | grep nixos
sudo nix-channel --add https://channels.nixos.org/nixos-26.05 nixos
sudo nixos-rebuild switch --upgrade
(26.05 is an example stable line from the manual at the time of writing; substitute the current nixos-YY.MM from channels.nixos.org.)
Same upgrade as two steps:
Flake host: update all inputs, then rebuild:
cd /etc/nixos # or wherever the system flake lives
nix flake update
sudo nixos-rebuild switch --flake .#hostname
Unattended channel upgrades without reboot:
Flake host: scheduled rebuild from a pinned lockfile (refresh lockfile separately):
{
system.autoUpgrade.enable = true;
system.autoUpgrade.flake = "github:owner/nixos-config#myhost";
system.autoUpgrade.upgrade = false;
}
References¶
- NixOS manual — Upgrading NixOS — channels,
--upgrade, schema warning,system.autoUpgrade - Official NixOS channels — live channel URLs and status
system.stateVersion(option search) — do not bump casually; not the package channelsystem.autoUpgrade.flake(option search) — flake URI; mutually exclusive withchannelsystem.autoUpgrade.upgrade(option search) —--upgradeflag whenchannelis nullnix-channel(nix.dev) —--updateand channel generationsnix flake update(nix.dev) — refreshflake.lock(experimental CLI)