The Complete Computing Environment

"The manual appears to depend on the location of Nixpkgs"


For the last month or so I haven't been able to update My NixOS configuration because nixpkgs build would fail. I can build and deploy the system once with an updated nixpkgs but future invocations would fail:

          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/rename.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/system/etc/etc.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/system/etc/etc.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/system/etc/etc.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/system/etc/etc.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/system/etc/etc.nix" />
[...redacting much of this]
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix" />
          <string value="3y2ymjdad71ilw7rpl71xwsj0pv9js36-nixpkgs/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix" />
The manual appears to depend on the location of Nixpkgs, which is bad
since this prevents sharing via the NixOS channel.  This is typically
caused by an option default that refers to a relative path (see above
for hints about the offending path).

Something about my system's invocation of the subsystems which dynamically generate the OS configuration manpages man configuration.nix and co were failing to strip the nixpkgs path from the docbooks which were being generated. I could disable the documentation but I use the documentation a lot when developing Arroyo, when assembling the Wobserver, when updating my system. I can't simply disable that and rely on "oh just grep the nixpkgs source code or use this webpage someone else hosts"… In fact I'm using it right now to draft this blog post which will then reintegrate in to my system!

But I couldn't update more than once:

Frustrating. And no one really has seen anything like this or could tell me much about how to fix it. I spent some time the last few weeks trying to figure out how to build My NixOS configuration as a nix flake since that would make it easier to bisect or narrow down problems without having to do all this nix-channel chicanery but Morph cannot deploy a flake right property right now without a shim that someone describes but does not show and so I am resorting to sillier methodologies.

Briefly: NIX_PATH

The Nix Pills guide talks about NIX_PATH in chapter 15.

NIX_PATH is used to resolve things like import <nixpkgs> and in the default configuration this points to a few places:

nix-instantiate --eval -E '<nixpkgs>'
NIX_PATH=/home/rrix/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels nix-instantiate --eval -E '<nixpkgs>'
NIX_PATH=/home/rrix.nix-defexpr/channels:nixpkgs=/home/rrix/Code/nixpkgs nix-instantiate --eval -E '<nixpkgs>'
NIX_PATH=nixpkgs=/home/rrix/Code/nixpkgs nix-instantiate --eval -E '<nixpkgs>'

Overriding my NIX_PATH to build with local nixpkgs

To bootstrap my system back together I updated my nixpkgs checkout to the version listed on and then Morph'd Meadow Crush, my GPD Pocket, as a development mule to validate that it wouldn't have the same issues.

[nix-shell:~/Code/nixpkgs]$ export NIX_PATH=nixos=/home/rrix/Code/nixpkgs/nixos:nixpkgs=/home/rrix/Code/nixpkgs:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels;
[nix-shell:~/Code/nixpkgs]$ morph deploy ~/org/cce/nixlib/nixops/laptops.nix switch --on=meadow-crush --passwd

And then I did it again. And then I did it from within Meadow Crush. The only problems are that a few GUI applications miss the Binary Cache, well okay, that's fine at least I'm not running out of date software with bugs fixed upstream.

I took the plunge and had Meadow Crush deploy back to my Framework laptop, Virtuous Cassette, and that worked:

[nix-shell:~/Code/nixpkgs]$ cat /etc/os-release  | grep BUILD_ID

But I still cannot "simply" update my system channels and deploy! In theory I could spend some time tracking down the differences in the evaluation, but I simply would rather not. In fact, I have wanted to move away from using channels in general so that I could have a declarative pin for my nixpkgs version. I could just … have that. With flakes you don't need to have a nixpkgs lying around to bootstrap your system and with this model you still do, though frankly I am not so concerned with that as I use Syncthing already to keep this all in a reasonable state of flow.

And so what if I just make my single-admin systems use the nixpkgs i already have cloned?

{ ... }:

  nix.nixPath = [

This can and should be set to the local user's defexpr file as well, which prevents Nix from recreating the channel definitions and modifying NIX_PATH to include them:

  nixpkgs = import /home/rrix/Code/nixpkgs {};
  nixos = import /home/rrix/Code/nixpkgs/nixos {};
{ config, pkgs, ... }:

  home.activation.defexpr = pkgs.lib.mkActivationLocalLink config

We'll see how fucked up this is, but now at least I can Flood the Arroyo. I had to move ~/.nix-defexpr/ away because the nix-daemon module which defines this nixPath variable adds a bit to the default system profile without a disablement flag.

if [ -e "$HOME/.nix-defexpr/channels" ]; then
  export NIX_PATH="$HOME/.nix-defexpr/channels${NIX_PATH:+:$NIX_PATH}"

ehehehehe thanks homie.

Keeping my nixpkgs checkout up to date

Updating the Nixpkgs checkout can be by invoking something like cce/update-nixpkgs-checkout:

(use-package plz)
(defun cce/update-nixpkgs-checkout ()
  (let ((path "/home/rrix/Code/nixpkgs/"))
    (with-current-buffer (find-file-noselect path)
      (let* ((channel-status (split-string
                              (plz "GET" "")
                              " "))
             (nixpkgs-unstable-ts (string-to-number (second channel-status)))
             (nixpkgs-unstable (first channel-status)))
        (magit-fetch-all nil)
        (magit-merge-plain "origin/nixpkgs-unstable")
        (message "updated nixpkgs checkout to %s"
                 (format-time-string "%c" nixpkgs-unstable-ts))))))
(provide 'cce/nixpkgs)

This relies on plz pulled in by Ement.el, and Magit. I'm sure the continuing tarpit of the lovely little local minima I've constructed here will continue to be sustainable.