How to pin config.nix?

I’ve got a basic single-user config that I’ve begun sharing with a colleague: https://github.com/ldeck/nix-config.

When he went to install nix (we’re both on macOS) and then run nix-env -iA nixpkgs.myPackages there were a few packages that didn’t install as he was on a more recent channel version of nixpkgs (we’re both on nixpkgs-unstable but I hadn’t updated in a while).

Would it be recommended to do something like the following to pin the nixpkgs? Does this flow through to overlays?

~/.config/nixpkgs/config.nix

let 
  fixed = import (builtins.fetchTarball(...)) {};
in {
  allowUnfree = true;
  packageOverrides = pkgs: with fixed; rec { ... };
}

There are many ways to achieve this with Nix, currently, but I might recommend a more portable approach that may appeal to you.

You can specify a pinned nixpkgs, and a specific pinned overlay set, right in your Nix file if you want, without needing to modify the user-wide nix.conf. No need for any setup at all now.

I prefer this for working on my public nix projects like nixpkgs-wayland, because it trains me to remember to craft my nix files and nix-build commands as if they will run on a random users’ computer.

Here’s what an example of that might look like:

nix-build ./example.nix => should give you exactly:
/nix/store/20mzhmi5vwb4m118kmpk583iknqjr41s-redshift-7da875d34854a6a34612d5ce4bd8718c32bec804

let
  # current 'nixos-unstable'
  nixpkgsRev="28fce082c8ca1a8fb3dfac5c938829e51fb314c8";
  pinnedNixpkgs = builtins.fetchTarball {
    url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsRev}.tar.gz";
    sha256 = "1pzmqgby1g9ypdn6wgxmbhp6hr55dhhrccn67knrpy93vib9wf8r";
  };

  # current 'master'
  waylandRev="0316a9ae0322380ba7daf02e2550570147023a78";
  nixpkgsWaylandOverlay = builtins.fetchTarball {
    # the default.nix in this repo is an overlay (fn).
    url = "https://github.com/colemickens/nixpkgs-wayland/archive/${waylandRev}.tar.gz";
    sha256 = "1cpa4cahlnsp7xjf4hhvmpqnl2zk34kwg8g3m867ziw7f4ib2gkh";
  };

  pkgs = import pinnedNixpkgs {
    config = { allowUnfree = true; };
    overlays = [ (import nixpkgsWaylandOverlay) ];
  };
in
{
  this_is_some_output = with pkgs; [
    # this pkg only exists in the overlay    
    redshift-wayland
  ];
}

(edited to also include unfree in the example)

1 Like

Thanks @colemickens for the example. Do I understand correctly that your wayland overlays are pinned to the version of nixpkgsRev?

So as I ponder your example further — in the meantime to pin my packageOverrides in ~/.config/nixpkgs/config.nix and the overlays within ~/.config/nixpkgs/overlays/*.nix is this all I need to do?

~/.config/nixpkgs/config.nix

let
    nixpkgsRev="28fce082c8ca1a8fb3dfac5c938829e51fb314c8";
    pkgs = builtins.fetchTarball {
      url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsRev}.tar.gz";
      sha256 = "1pzmqgby1g9ypdn6wgxmbhp6hr55dhhrccn67knrpy93vib9wf8r";
    };
in
{
  allowUnfree = true;
  packageOverrides = pkgs: with pkgs; rec {
     ...
  };
}

Or do the overlays in ~/.config/.nixpkgs/overlays/*.nix need to be specifically imported in a similar way to what you’ve done?

I would recommend a quick read through the manual chaper on overlays. Overlays provide package definitions that layer on top of an imported nixpkgs. So, they themselves don’t pin a nixpkgs (though some overlay authors will pre-build their packages ontop of popular nixpkgs channels to pre-populate binary caches for users).

In the example that I’m giving, we’re importing our own specific version of nixpkgs, and explicitly applying a specific version of the overlay. In this way, the local configuration (~/.config/nixpkgs/...) is completely ignored, so there’s no need to be concerned about what state they are in. But this is only valid in the scope of that file.

If you really need this to apply user-wide, then my example is only partially applicable, and you have gotten the important part.

Something like what you showed should work for overiding specific packages to come from the specified pinned nixpkgs. However, since overlays are a different beast, they look different. And when you specify overlays in ~/.config/nixpkgs/overlays/..., the nix file would just return the result of the fetchTarball (or whatever file from the overlay contains the actual overlay function. Sometimes that’s the default.nix, sometimes that’s an overlay.nix.)