Nix Container Declarative Package Management
As discussed in lsupg Nix Support, lsupg does not work well with Nix containers because Nix does not provide a way to upgrade all packages by attribute path. Nix provides a way to upgrade all packages by name, but that does not do the right thing.
The “correct” way to manage “installed” Nix packages is to do so
declaratively using attribute paths. If the file used to do this is
standardized, then lsupg
can use that file to determine
what upgrades are available. I want to work through a test by hand
before I decide how to proceed.
Major props go to Ian Henry for his How to Learn Nix blog series. I recommend reading all of it, but this blog entry is based on the Setting up a declarative user environment post in particular.
Configuration
I am tentatively declaring environment packages in an
/etc/nix/packages.nix
configuration file.
The configuration is just a list of attribute paths for all packages
that you want installed in the environment. The nixos/nix image only has
nix
installed, so the default configuration is as
follows:
with import <nixpkgs> {}; [
nix
]
Test
I am performing my test in an ephemeral Docker container, to ensure that I do not change the Nix environment on my host system.
$ docker run --rm -it --hostname nix nixos/nix
I created an /etc/nix/packages.nix
configuration file
with the following content, continuing to use a Python 3 package for
testing:
with import <nixpkgs> {}; [
nix
python3
]
To test an upgrade, I installed an old version of Python 3 using the following Nix expression:
let
pkgs = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/20.09.tar.gz";
}) {};
in pkgs.python3
This installed Python 3.8.5:
nix:/# nix-env -if tmp/test.nix
installing 'python3-3.8.5'
...
The currently installed packages can be queried as follows:
nix:/# nix-env -q
nix-2.3.11
python3-3.8.5
The packages that would be installed after an upgrade can be queried as follows:
nix:/# nix-channel --update
unpacking channels...
created 1 symlinks in user environment
nix:/# nix-env -qaf /etc/nix/packages.nix
nix-2.3.12
python3-3.8.9
The lsupg
Nix module can process these two lists of
packages and calculate what upgrades are available by comparing package
names and version numbers. In this case, both the nix
and
python3
packages have upgrades available. Note that the
python3
upgrade is correct, not to the latest alpha
version.
To test further, I upgraded both packages:
nix:/# nix-env -irf /etc/nix/packages.nix
...
After this upgrade, the list of installed packages matches the list of packages that would be installed after an upgrade:
nix:/# nix-env -q
nix-2.3.12
python3-3.8.9
nix:/# nix-env -qaf /etc/nix/packages.nix
nix-2.3.12
python3-3.8.9
This looks good! I am heavily leaning toward changing
lsupg
to calculate available upgrades in this way.