Pinning nixops builds []

Pinned nixops

On one machine my Nixops builds and deploys, but on the other one it fails. Why? Isn’t nix supposed to deliver reproducible builds? Turns out nixops uses by default your system configurations’ channels rather then a pinned nix packages. Which is not why you’re using nix. You want a reproducible build, in other words, either both machines fail for the same reason or both succeed. We will discuss how to do this for nixops in this post trough a pin.

To pin a nixops deployment we create a shell1 from which we run nixops:

let
   pkgs = import ./pin.nix { };
in

  pkgs.stdenv.mkDerivation{
  name = "nixops-env";
  NIX_PATH="nixpkgs=${pkgs.path}";
  buildInputs = [ pkgs.nixops ];
  }

Where pin.nix looks like this:

let 
hostPkgs = import <nixpkgs> {};
pinnedPkgs = hostPkgs.fetchFromGitHub {
    owner = "NixOS";
    repo = "nixpkgs-channels";
    # nixos-unstable as of 15.06.2019
    rev = "1601f559e89ba71091faa26888711d4dd24c2d4d";
    sha256 = "0iayyz9617mz6424spwbi9qvmcl8hiql42czxg8mi4ycq4p1k0dx";
};
in
import pinnedPkgs {
    # since I also use this for clients I don't want to have to care
    config.allowUnfree = true; # took me too long to figure out
}

This is also possible for reflex-platform projects where we simply depend on the provided pin:

   pkgs = ((import ./reflex) { }).nixpkgs;

Conclusion

In this post we discussed how to pin nixops builds. There are other ways to do pinning, which is described here. I found it hard to get a working solution from that thread, therefore I recorded my own solution here.


  1. For my reflex project I simply made an alternative shell, because reflex-platform doesn’t make the shell easily modifiable. you can run a different shell by providing the filename to the nix-shell command: nix-shell nixops-shell.nix 

Recent stuff

Tags