Simple single package pinning on NixOS

The ability to pin a given package in NixOS is pretty useful, for cases such as:

Trying to find out how to pin a single package to a particular channel, or nixpkgs SHA simply and from within configuration.nix, I found myself going around in circles, there are a lot of possibilites, and different guidelines based on different versions of Nix. Also, none of them were too clear on how it would actually integrate into a configuration.nix expression.

That was until I stumbled upon this NixOS configuration on Github, which presents a simple, flexible, and easy to understand method for selectively pinning individual packages.

As an aside, searching Github using advanced search, specifying Nix as a language, and filename matching configuration.nix seems to be a pretty useful approach for finding useful examples and solutions, from people's published Nix configurations.

The approach used in the above configuration.nix boils down to something like this:

{ config, pkgs, lib, ... }:

with builtins; let

  unstable = import <unstable> {};

  homeAssistantPin = import (pkgs.fetchFromGitHub {
      owner = "Mic92";
      repo = "nixpkgs";
      rev = "9bb6948317a895915f74bf9a31bc178862b6cfa1";
      sha256 = "0jj1myb2d4k18cpg3rcb32fb0yb5nzd9gb33jyf9sz7n3ggm7hrq";
    }) {};

in {
  # ...

  environment.systemPackages = with pkgs; [
    vim
    fish
    # install a package from unstable
    unstable.htop
    # install a package from the named pin
    homeAssistantPin.home-assistant
  ];

  # ...
}

In this case, I'm attempting to pin home-assistant to a SHA referencing the branch for a PR which solves an issue with a python dependency when installing the package.

Getting the pre-fetched SHA works a bit like this:

$ nix-prefetch-github --rev 9bb6948317a895915f74bf9a31bc178862b6cfa1 Mic92 nixpkgs
{
    "owner": "Mic92",
    "repo": "nixpkgs",
    "rev": "9bb6948317a895915f74bf9a31bc178862b6cfa1",
    "sha256": "0jj1myb2d4k18cpg3rcb32fb0yb5nzd9gb33jyf9sz7n3ggm7hrq"
}

In this case I am trying to pin home-assistant, which additionally required the package to be explitly specified as follows:

{
  services.home-assistant = {
    enable = true;
    package = homeAssistantPin.home-assistant;
    # ...
  };
}