Installing Older Pkgs in NixOS

Published on 2016-04-24

Sometimes with NixOS, or nixpkgs, you might find yourself in the situation where you can’t update a specific package that has been bumped over the regular channels.

Well you’re in luck! The process to pin a package is pretty straight forward, albeit a bit involved:

  1. First we need to find the revision of nixpkgs, that has:
    1. The version you target
    2. Cached binaries, so that you don’t need to recompile everything
  2. Fetch and import the old expressions
  3. Override the package(s) you want to pin


Beginning with finding the revision you want; Start with looking at the nixpkgs channels. Picking a revision from nixpkgs-channels means that the hydra installation at TU Delft has successfully tested and built the system packages at that revision. Lets say we’ve identified the revision b8755a4cdf8dd426ac642c006825d302dfe5f4b1 as the latest one that still contains our wanted package version. To get the hash you can use nix-build and the helper function fetchFromGitHub to fetch an archived set of nix expressions.

nix-build -E 'with import <nixpkgs> { }; fetchFromGitHub { owner = "NixOS"; repo = "nixpkgs-channels"; rev = "b8755a4cdf8dd426ac642c006825d302dfe5f4b1"; sha256 = "1bsxdq7c7jijnghy1lng6fckr8x7nh8yxj9iarkwnzw9mxm44h15";}'
output path ‘/nix/store/204q0xz0g6hxigjhz5h88s6i2c88gjwr-nixpkgs-channels-b8755a4cdf8dd426ac642c006825d302dfe5f4b1-src’ has r:sha256 hash ‘0hjbrhhab9hixdhzrmgz6kxqrwinfdjll7w5jk2v478s84l8i4yx’ when ‘1bsxdq7c7jijnghy1lng6fckr8x7nh8yxj9iarkwnzw9mxm44h15’ was expected
error: build of ‘/nix/store/rbhvc89vq3pbpg68vvbvbfhqdqwzjkqd-nixpkgs-channels-b8755a4cdf8dd426ac642c006825d302dfe5f4b1-src.drv’ failed

The above sha256 is fake and is just there as a place holder, it will make the fetchFromGitHub call to spit out the correct hash. As you probably realize this method isn’t great since the expressions will have to be re-downloaded. But since fetchFromGitHub is using fetchzip there is an alternative way of getting them, which is to rely on the nix-prefetch-zip build support script in the nixpkgs repository.

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   164    0   164    0     0    314      0 --:--:-- --:--:-- --:--:--   321
100 14.6M    0 14.6M    0     0  2224k      0 --:--:--  0:00:06 --:--:-- 3287k
hash is 0hjbrhhab9hixdhzrmgz6kxqrwinfdjll7w5jk2v478s84l8i4yx
path is /nix/store/psa5sxrah00vwjaf616dagkzfn9nvr9j-b8755a4cdf8dd426ac642c006825d302dfe5f4b1.tar.gz

Here ~nixpkgs is just my zsh diralias to the nixpkgs checkout. This method isn’t great either since it requires you to have an unpacked clone of nixpkgs available. Anyway we now have the sha for the expression archive and we can use this information to override desired package(s).

  packageOverrides = self: with self; let
    fetchNixPkgs = { rev, sha256 }:
    fetchFromGitHub {
      inherit sha256 rev;
      owner = "NixOS";
      repo = "nixpkgs-channels";
    pinnedPkgs = import (fetchNixPkgs {
      rev = "b8755a4cdf8dd426ac642c006825d302dfe5f4b1";
      sha256 = "0hjbrhhab9hixdhzrmgz6kxqrwinfdjll7w5jk2v478s84l8i4yx";
    }) {};

  in {
    inherit (pinnedPkgs) texLiveFull;

Translated the above code says that texLiveFull should be set to the one in pinnedPkgs where pinnedPkgs is the imported and parameterized set of packages as fetched by the fetchNixPkgs function that we declare. This in turn is just a fetchFromGitHub wrapper since the owner and repo won’t change between different versions and is useful if we need to mix packages from different revisions.

Finally we can stick this in either a NixOS configuration.nix, under the nixpkgs.config attribute, or in our user ~/.nixpkgs/config.nix.

As pointed out by Domen Kozar; Since Nix-1.9 we could just as well have used the nix builtin fetchTarball, this does comes with the caveat of not being able to specify a checksum for the expressions, potentially injecting and evaluating unintended nix expressions.