Finally figured out how to set up my systems a couple months ago, and have been using them happily ever since, but realized that it's time to update stuff. My NixOS setup involves declarative package management using Home Manager, but completely forgot the basics and wasn't sure if Home Manager would complicate things as the repo only mentions the home-manager tool which I don't have.
- 1,128
2 Answers
TL;DR
Are you on the latest channel?
(See how to check and set below.)sudo nix-channel --updatea. (declarative/NixOS)
sudo nixos-rebuild switch
b. (ad-hoc)nix-env -u '*'
c. (Home Manager)home-manager switch(I think)
These steps should work regardless of using NixOS or not.
NOTE-1 (flakes): It's a fairly good bet that none of this will work if you are using flakes.
NOTE-2 (NixOS + Home Manager): If nixos-rebuild switch fails with cryptic error messages, look at your Home Manager config. At least, in the past 5 years, whenever the error wasn't clear (e.g., nix.maxJobs deprecated in favor of nix.settings.max-jobs), it was always something about Home Manager.
Step 0. Check and set the latest channel
Step 1.'s nix-channel --update will only pull the changes in the channel that is currently set! To check the current one you are subscribed to, issue
sudo nix-channel --list
The latest NixOS manual's Chapter 4. Upgrading NixOS will always show the name and the link of the latest channel. The Nix Channel Status page is also a very good resource.
For example, I was subscribed to channel 20.09 so I needed to update it to 21.11 by doing
$ sudo nix-channel --list
nixos https://nixos.org/channels/nixos-20.09
$ sudo nix-channel --remove nixos
$ sudo nix-channel --add https://nixos.org/channels/nixos-21.11 nixos
More info:
The Nix manual's 4.4 Channels section is a short intro to Nix channels.
The NixOS wiki's Nix channels article goes more into the details and has a good summary on the basic commands. (Personally, I found this one more useful.)
Step 1. Update the channel
This is required both for declarative and "ad-hoc" [sic] setups3:
sudo nix-channel --update
Even though the Nix manual has a 4.1 Basic Package Management section, it is best documented in the NixOS manual (see Chapter 7. Package Management). (Albeit, I didn't find it straightforward figuring out the correct order of steps from these; the biggest help was this NixOS discourse thread.)
Home Manager does not seem to complicate this process. (At least, I'm using it on NixOS, and nixos-rebuild switch always takes care of everything with my setup.)
TIP FOR NIXOS USERS
Thenixos-rebuild switch --upgradecombines Step 1. and Step 2. as it "is equivalent to the more verbosenix-channel --update nixos; nixos-rebuild switch".
Step 2. Update the packages
The two adjectives, "ad-hoc" [sic] and "declarative", are introduced in the NixOS manual to differentiate the two modes of Nix package management3:
"ad-hoc": Managing packages with
nix-env.1"declarative": In the NixOS manual, this refers to declaring packages as a list in NixOS'
configuration.nix, but it can be done in many other ways2.
The commands:
a. To update all packages declared in NixOS' configuration.nix, use:
sudo nixos-rebuild switch
b. To update all packages installed with nix-env:
nix-env -u '*'
c. To update all packages installed using Home Manager:
home-manager switch
(I think. Again, I'm using Home Manager in NixOS, and never had to touch any Home Manager commands. See Home-manager equivalent of “apt upgrade”)
Footnotes
[1]: As far as I know, the NixOS manual is the only official document that uses the term "ad-hoc [sic] package management" and only to mean package management using nix-env.
(Therefore I find the term misleading, because using packages via nix-shell -p commands or custom shell.nix-es are also ad hoc forms of package management. Also, nix-env can be messy.)
[2]: For example with Home Manager, using shell.nix-es, flakes. (It is probably incorrect to list flakes, as it is a mechanism that can be used with Home Manager and nix-shell Nix expressions...)
[3]: Not sure if there is a consensus what "ad-hoc", "declarative", and "imperative" package management means in Nix; footnote 1 has my thoughts about "ad-hoc", some say that using channels is always an imperative form of package management, so "declarative" seems to be overloaded...
- 1,128
TLDR use nh with the new --update flag
This is a new feature of nh, and it looks like this:
$ nh os switch --update ~/config
It assumes:
- you're using flakes (via a file at
~/config/flake.nix) - your flake output is the same name as your computer's hostname
This is a newer option.
Keep scrolling for the old tried and true ways, and for how I make it more convenient.
This answer below should be useful to
- anyone thinking of switching to using flakes for their system or
- anyone dissatisfied with the output of the old standard
nixos-build.
How to update every package on NixOS?
Toraritte's answer covers the older NixOS installation with channels, but does not cover flakes, so I'll try to answer this question for NixOS with Home Manager in the context of flakes - which coincidentally enough I've been using lately.
I think, in exchange for a little more complexity from wrapping your NixOS configuration, flakes makes the updating of channels and switching much simpler, and allows you to define your channels in the config instead of environmentally, which holds more true to the Nix promise of reproducibility.
The below nix flake is adapted from my own configuration, tightened up:
{ inputs = { # Two inputs, nixpkgs and Home Manager:
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
home-manager = {
url = "github:nix-community/home-manager/release-24.11";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, home-manager, ...}: {
nixosConfigurations.x1 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ # Six modules:
({ pkgs, ... }: {
environment.systemPackages = with pkgs; [
nh
];
programs.bash.interactiveShellInit = ''
switch () { # hostname default for flake output - mine is `x1`
nh os switch --update ~/config ;
}
'';
})
./console.nix # console/shell module
./gui.nix # gui specific module
./x1.nix # machine specific module
home-manager.nixosModules.home-manager
{ home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = false;
home-manager.users.aaron = { imports = [ ./home.nix ]; };
}
];
};
};
}
This flake.nix config is adapted from my personal config with just the important stuff relevant to this question in the first module listed: the inclusion of the nh package and the bash commands I use to make it convenient to execute the process of manually updating.
(Note there is now a nh option that includes more functionality than installing just the package, but you should look at that separately.)
I define a bash function, switch, which runs nh os switch --update ~/config where ~/config is my configuration repo.
The --update part does similarly to the below:
$ nix flake update ~/config
warning: Git tree '/home/aaron/config' is dirty
warning: updating lock file '/home/aaron/config/flake.lock':
...
The above step does not actually update your system, it only updates the inputs in the lockfile.
But with nh, you can build and switch over to your updated inputs in one step with the switch function we wrote:
$ switch # runs: nh os switch --update ~/config
> Building NixOS configuration
...
With this command that uses nh, the output is much more verbose and informative than the usual output on a nix build, where every logged line overwrites the prior. I consider this a big improvement over the old standard nixos-build because I want to see as much as possible, and I seem to learn something new every time I do it.
Here's sample output with the log, the dependency tree, and the builds and downloads table:
Quieting the output (or if you don't have nh yet)
But you may prefer less information in the output. If so, then you would prefer not to use nh, so you can do:
switch () { # usage: switch x1
sudo nixos-rebuild switch -L --flake ~/config#$1 ;
}
$ switch x1 # where x1 is my flake output and my hostname
Remove the -L (short for --print-build-logs) if that's still too verbose, or try the --quiet flag.
Issues with sudo
The nh command is intended to be used without sudo, and only asks you to input your password where absolutely necessary.
If you've been using sudo to upgrade your system's flake, you might find the flake.lock file and the .git/index files are now both owned by root. To fix this, do
$ sudo chown aaron flake.lock .git/index
of course, substitute your own username for mine above.
Conclusion
To recap, we've looked at how to use nh to update your NixOS via flakes in a single command, and how to structure your flake.nix config to handle this, while working around several potential problem spots.
Your feedback is absolutely welcome! Please comment below.
- 5,038
