Skip to main content

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.

Author

Travis Cardwell

Published

Tags
Related Blog Entries