How do I update a single package installed with a standard config file?

There seems to be a dozen different ways to install packages on NixOS, so googling for help keeps giving me results for things like flakes, “nix profile”, and “nix env”, which I’m not familiar with.

I’ve install all my packages using what seemed to be the standard config file:
/etc/nixos/configuration.nix

  environment.systemPackages = with pkgs; [
    android-tools
    chromium
    cryptsetup
...

When installing something, I add it to that list and run sudo nixos-rebuild switch or if I want to install something temporarily, I just run nix-shell -P pkg.

I now need to update signal-desktop to the latest version, but I don’t want to update any other installed packages. How can I do that?

2 Likes

The way I understand it is that this is not really intended because that would just increase the amount of dependencies that you need. So there is no way to keep the old ones and just declare that new one but there is a way to declare that you want to keep the older versions of the other programs you use. This is done through overrides. In that case you need to specify how that package is supposed to be build.

I can’t even do a one-off with nix-shell?

I thought one of the main benefits of NixOS was that packages were installed with all of their dependencies independent from other packages. Shouldn’t that make upgrading a single package easy? What do you recommend I do?

Going through all the dozens of packages I’ve installed and pinning them with explicit versions seems like a lot of work. Eventually I’m going to want to upgrade them, but not every time I want to bump a single package version.

1 Like

Is the update you need available in any of the existing channels?

If so you can define a separate channel for some of your packages:

https://www.zknotes.com/page/alternate-nixpkgs-in-flakes-nixos

As far as I understand if it’s not in the existing channels and you need it now then you will have to do some more manual work.

1 Like

Assuming the version of signal-desktop you want has already been packaged, you can “pin” the package, following the instructions from the NixOS Wiki on Pinning Nixpkgs. Specifically, you can do something like this:

  environment.systemPackages = with pkgs; 
    let myPkgs = import (builtins.fetchTarball {
        url = "https://github.com/NixOS/nixpkgs/archive/9957cd48326fe8dbd52fdc50dd2502307f188b0d.tar.gz"; #Change this URL accordingly
    }) {};  in [
      android-tools
      chromium
      cryptsetup
      myPkgs.signal-desktop
      ...
  ];

To find the right URL, you can use Nix Package Versions

1 Like

Solutions have been mentioned, but I’ll try to add some clarification:
NixOS is based on the nixpkgs repo. Whenever you build a system generation, this is connected to a certain commit in this repo, which means you will get the program versions (e.g. for Signal Desktop) as defined by this commit.
When you update, either via nix-channel --update or via nix flake update, you look up the nixpkgs repo and move your inputs for the next rebuild to the latest commit in a certain branch of Nixpkgs.
To mix program versions of different age, you can have multiple named pointers to different commits in nixpkgs (and other repos). The you can select the desired package via the named pointer. By default you get pkgs and the with pkgs;" tells nix to look up e.g. chromium by name and if not found to continue searching in the pkgs namespace.
When you follow the posted solutions, you will mainly find people using the current release of NixOS and mixing in the unstable branch, but you can also import the release-14.04 as oldandtrusty and then use oldandtrusty.firefox in your configuration.
If you need a special version of a program you need find a matching commit in the nixpkgs history where this exact version was defined/packaged.
That said, if the build recipe for the desired package hasn’t changed, it is often desirable to simply override the version and source hash to benefit from sharing dependencies with your base set of packages.

3 Likes

Can you elaborate a little bit more what you mean by that? In my case, for example i’m on channel 23.11 but there is an update of vscode in the same channel 23.11. But instead of updating the whole system, i’m only whant to update vscode

A channel is all-or-nothing. A version of a channel corresponds to a particular Git commit of Nixpkgs; when you update your channels, you’re fetching the latest such commit. Then every package in your configuration, which uses your system channel as its source of packages by default, will be updated.

So in order to update only a single program, you want to get the definition of the package from an alternate source, not your system channel. That’s what this comment is showing you how to do. Then don’t update your channels; just rebuild your system configuration. Nix will pull down a second copy of Nixpkgs into your store corresponding to the pinned commit, and any packages you reference from that source will have the versions they have in that commit.

3 Likes