JMM’s

Notes on Nix/NixOS

A mutable page about an immutable package manager.

I should probably split this into separate pages. There’s Nix the language, Nix the package manager, nixpkgs the list of packages, and NixOS the operating system. There’s also nix flakes, which I haven’t used too much yet.

Nix allows you to do cool things like:

I got into Nix because I would read John Wiegley’s personal .emacs configuration. He used to use git submodules to manage his complex Emacs dependencies, and then one day I noticed he switched to this thing called Nix. I first used Nix to also manage Emacs stuff (on Debian), then I eventually switched to NixOS.

Command Line stuff

This section might already be out of date, since some arguments have changed.

Start a Nix REPL with specific channel

nix repl -I nixpkgs=channel:nixos-unstable "<nixpkgs>"

These arguments may change later. You can also use specific channels like nixos-21.11

NixOS configuration REPL

nix repl "<nixpkgs/nixos>"

You can look at configured variables under the config set. For example: config.networking.hostName will say your configured hostname.

Build and install package from channel

Here’s one way to install the latest yt-dlp:

nix build -f channel:nixos-unstable yt-dlp

This just builds (or usually just fetches) the derivation and stores the result in “./result” in the current directory. You can then install it with:

nix-env -i ./result

This is pretty imperative, and some would argue that a more proper thing to do would be to manage this in either your NixOS config or Home Manager. I won’t argue that. Sometimes upgrading all packages breaks them in weird ways. This might be fixed by Flakes.

Garbage collect old NixOS system profiles

As root (e.g. using sudo) run:

nix-env --list-generations --profile /nix/var/nix/profiles/system

To get a list of NixOS system generations. Then run:

nix-env --delete-generations +1 --profile /nix/var/nix/profiles/system --dry-run

to delete everything except your current generation. Of course, you’d do this without the --dry-run argument. You can also supply specific generation numbers instead of +1.

Find the version of nixpkgs

nix-instantiate --eval '<nixpkgs>' -A lib.version

And this gives you something like "23.11.7870.205fd4226592"

Building derivations remotely

I can build stuff on my laptop, but my laptop is pretty weak. For some things it’s better to build derivations remotely. The following command will probably not make sense, but it’s what I used when generating analyses while doing neuroeconomics research on risk in rodents:

nix build -v -L -f . history-logistic-stan-plot-html --arg limitSubjects ./acth-subjects.txt --builders 'ssh://remote-builder1 - - 20' --max-jobs 0 --argstr acthEpoch pre -o outputs/histlogis-plot-acth-pre.html

The problem with building this way is that you’ll need to send derivations to the remote builder, and this kind of happens in serial. If the connection to the remote builder has a lot of latency (which ours did since it was in Shanghai), it can take a long time to even evaluate the derivation. So sometimes what I’d do is just log into the remote builder and evaluate the derivation on that machine. I think I’d need to sign the output there (which I should have documented). Then I’d copy it over with something like:

nix copy -v --from ssh://remote-builder1 --trusted-public-keys "remote1-cache:░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░" -f . --arg limitSubjects ./good-subjects.txt week-risk-over-time-aggregate

Building your own packages

Say you write a Nix derivation in a file, then you want to build it.

# Old way, doesn’t work
nix build "(with import <nixpkgs> {}; callPackage /path/to/some/package/btrfs-snapshot-pkg.nix {})" -o some-output
# New way
nix build --impure --expr "(with import <nixpkgs> {}; callPackage /path/to/some/package/btrfs-snapshot-pkg.nix {})" -o some-output

I’m sure there’s a better way with flakes (which’ll save evaluation time), but this is what I used to do.

Repairing the nix store

Say that your disk is old and also pretty close to full and you’ve started noticing some builds will fail with errors where they normally would work. It’s probably that something in your Nix store is corrupted. This is totally a hypothetical, and not at all what happened to me yesterday and several other times because I should replace my dying disk.

Fortunately, Nix can actually detect and repair corrupt paths. This is something you can’t really do with typical imperative-installed packages.

Anyway, here’s what I do.

# Repair the store in a systemd service
systemd-run -u repairing-store nix-store --verify --check-contents --repair
# Oh no, you found out that repairing the store is really thrashing the disk.
# Time to slow it down so you can do actual work in the meantime
systemctl set-property repairing-store.service IOReadBandwidthMax="/nix/store/ 3M"
# Also, you should have just provided the previous parameter to the initial invocation with “-p IOReadBandwidthMax="/nix/store/ 3M"

# Maybe you just want to see how much it’s been reading.
watch --interval 0.2 systemctl show repairing-store.service --property=IOReadBytes

To-Dos

Errors

Some documentation for some errors I’ve encountered, as I’ve encountered them.

Bus error while rebuilding NixOS

Encountered on 2023-12-07

Trying to finally upgrade to 23.11. I’m getting the following error while building:

building '/nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv'...
unpacking sources
unpacking source archive /nix/store/n5s7zab7lp7y162lwakk3k6qvpzis6sf-xwayland-23.2.2.tar.xz
source root is xwayland-23.2.2
setting SOURCE_DATE_EPOCH to timestamp 1698198775 of file xwayland-23.2.2/xserver.ent.in
patching sources
updateAutotoolsGnuConfigScriptsPhase
configuring
mesonConfigurePhase flags: --prefix=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2 --libdir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/lib --libexecdir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/libexec --bindir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/bin --sbindir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/sbin --includedir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/include --mandir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/share/man --infodir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/share/info --localedir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/share/locale -Dauto_features=enabled -Dwrap_mode=nodownload --buildtype=plain -Dxwayland_eglstream=true -Dxcsecurity=true -Ddefault_font_path=/run/current-system/sw/share/X11/fonts -Dxkb_bin_dir=/nix/store/jlzjj0yn56pzgs5cwd69a335gb213sds-xkbcomp-1.4.6/bin -Dxkb_dir=/nix/store/w4m1s9q2hlisl2bbhxmlwmci1m7nxzdr-xkeyboard-config-2.40/etc/X11/xkb -Dxkb_output_dir=/nix/store/hg13f7gy7671hs6mwz5r39swlsav5iay-xwayland-23.2.2/share/X11/xkb/compiled -Dlibunwind=true
/nix/store/qrmvf49dbs7yqshymnqdhaiig0mcljlz-meson-1.2.3/nix-support/setup-hook: line 3:    25 Bus error               (core dumped) meson setup build "${flagsArray[@]}"
error: builder for '/nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv' failed with exit code 135
error: 1 dependencies of derivation '/nix/store/b6bl6r130285xkwvwvjl17a9zain90dv-man-paths.drv' failed to build
error: 1 dependencies of derivation '/nix/store/b4dm5ika5kya4z9g2mh60986i33vz9ff-system-path.drv' failed to build
error: 1 dependencies of derivation '/nix/store/aaj3m75x9czpxgblzb8cw1755jvgwcks-X-Restart-Triggers-polkit.drv' failed to build
error: 1 dependencies of derivation '/nix/store/r9y9ci2i9fw22qg6amvp8q9f78294vhz-dbus-1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/09bjggsj8fpnym3rfvf9g0kmjyxsckq9-etc-pam-environment.drv' failed to build
error: 1 dependencies of derivation '/nix/store/z5lgypqfb8yi2xf4sknyjgkkkzi6v0kr-man-cache.drv' failed to build
error: 1 dependencies of derivation '/nix/store/4kdnw0lq6agqjkbmv577g80nx18gh987-set-environment.drv' failed to build
error: 1 dependencies of derivation '/nix/store/9b62fw5yq875d2ilvb7hjy9q5g6ydm6s-unit-accounts-daemon.service.drv' failed to build
error: 1 dependencies of derivation '/nix/store/d0y49fm0s1migr0ccmff94ikif4mqpch-X-Restart-Triggers-dbus.drv' failed to build
error: 1 dependencies of derivation '/nix/store/clijrdlji2y8y672da9n96jnqlzlh5ym-etc-man_db.conf.drv' failed to build
error: 1 dependencies of derivation '/nix/store/6c7nkxscwi59ydq8i4r3sz7y4d0w8d59-etc-profile.drv' failed to build
error: 1 dependencies of derivation '/nix/store/qyq637v81j9n2yvf3yypyffmcrima4jb-etc-zshenv.drv' failed to build
error: 1 dependencies of derivation '/nix/store/2wyxrkdklscmzk21x4klfn2z289mklq6-unit-polkit.service.drv' failed to build
error: 1 dependencies of derivation '/nix/store/gas3wlyzjd96lcz1gqz4hfdcljfggq2r-unit-dbus.service.drv' failed to build
error: 1 dependencies of derivation '/nix/store/kjk081lvhz6hwrjbn8jm87lsl1aqxdmb-unit-dbus.service.drv' failed to build
error: 3 dependencies of derivation '/nix/store/x1pzsi502467fn6wfvqdpbrv0vrq59z7-system-units.drv' failed to build
error: 1 dependencies of derivation '/nix/store/mryj6fqplbb2yrcr6krkph3ajq9phpyx-user-units.drv' failed to build
error: 9 dependencies of derivation '/nix/store/lk2d4dh23zrly4mdq7vwhpb48vs6wm75-etc.drv' failed to build

I know that I may have corrupted some nix store paths when I accidentally turned off my computer mid-upgrade. So I’ll look for corrupted paths and try to repair them:

nix-store --verify-path $(nix-store -qR /nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv)

This returned nothing. Not sure if that’s good or bad.

Looking at journalctl I see:

Dec 07 21:00:45 ░░░░░ audit[59815]: ANOM_ABEND auid=1000 uid=30001 gid=30000 ses=3 subj=kernel pid=59815 comm="meson" exe="/nix/store/qp5zys77biz7imbk6yy85q5pdv7qk84j-python3-3.11.6/bin/python3.11" sig=7 res=1
Dec 07 21:00:45 ░░░░░ kernel: audit: type=1701 audit(1702011645.866:175): auid=1000 uid=30001 gid=30000 ses=3 subj=kernel pid=59815 comm="meson" exe="/nix/store/qp5zys77biz7imbk6yy85q5pdv7qk84j-python3-3.11.6/bin/python3.11" sig=7 res=1
Dec 07 21:00:45 ░░░░░ audit: BPF prog-id=338 op=LOAD
Dec 07 21:00:45 ░░░░░ kernel: audit: type=1334 audit(1702011645.883:176): prog-id=338 op=LOAD
Dec 07 21:00:45 ░░░░░ audit: BPF prog-id=339 op=LOAD
Dec 07 21:00:45 ░░░░░ audit: BPF prog-id=334 op=UNLOAD

I’m going to try to build it while keeping the failed output:

NIX_PATH=nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/░░░░░/configuration.nix:/nix/var/nix/profiles/per-user/root/channels nix build -vL --file "<nixpkgs/nixos>" system --keep-failed

Hmm… now that I think about it, why is it trying to build xwayland instead of fetch it from a cache? Did I override something a while back?

I’ll check to see why my system depends on it:

nix why-depends --derivation /nix/store/░░░░░-nixos-system-░░░░░-23.11.1431.░░░░░.drv /nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv
/nix/store/░░░░░-nixos-system-░░░░░-23.11.1431.░░░░░.drv
└───/nix/store/b4dm5ika5kya4z9g2mh60986i33vz9ff-system-path.drv
    └───/nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv

Welp, that’s not really helpful. Maybe I’ll compare its derivation to the standard xwayland derivation, since they seem to be different.

Comparing a diff of

  • /nix/store/llklx9i8w71yib3x6338lq8ldhdnbqnl-xwayland-23.2.2.drv (normal version)
  • /nix/store/1724qmj8zhyxibg1xqmrcnnj45anyipb-xwayland-23.2.2.drv (my weird version)

I see there’s a difference in mesonFlags:

Normal version:

      "mesonFlags": "-Dxwayland_eglstream=true -Dxcsecurity=true -Ddefault_font_path= -Dxkb_bin_dir=/nix/store/jlzjj0yn56pzgs5cwd69a335gb213sds-xkbcomp-1.4.6/bin -Dxkb_dir=/nix/store/w4m1s9q2hlisl2bbhxmlwmci1m7nxzdr-xkeyboard-config-2.40/etc/X11/xkb -Dxkb_output_dir=/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9/share/X11/xkb/compiled -Dlibunwind=true",

My version:

      "mesonFlags": "-Dxwayland_eglstream=true -Dxcsecurity=true -Ddefault_font_path=/run/current-system/sw/share/X11/fonts -Dxkb_bin_dir=/nix/store/jlzjj0yn56pzgs5cwd69a335gb213sds-xkbcomp-1.4.6/bin -Dxkb_dir=/nix/store/w4m1s9q2hlisl2bbhxmlwmci1m7nxzdr-xkeyboard-config-2.40/etc/X11/xkb -Dxkb_output_dir=/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9/share/X11/xkb/compiled -Dlibunwind=true",

Why is mine depending on /run/current-system/sw/share/X11/fonts? The sandbox won’t have access to that.

Checking out a nix repl for <nixpkgs/nixos> I see that config.programs.xwayland.package is indeed different than pkgs.xwayland. It looks like config.programs.xwayland.defaultFontPath is getting set somewhere. Maybe this has to do with this warning I ignored earlier:

trace: warning: The option `fonts.fonts' defined in `/░░░░░/configuration.nix' has been renamed to `fonts.packages'.

Looking at my settings, I see that I have the following:

  fonts = {
     fontDir.enable = true;
     # enableFontDir = true;
     fonts = with pkgs; [

I comment that fontDir.enable = true; line out. Now I see that the package matches up with the default one.

And now it builds correctly! (Though I haven’t checked if it actually works ;P)

Update: My meson was corrupted

2023-12-11

I was wrong. Actually, the problem was a corruped path. It turns out that my meson path was corrupted. See my hyperkey page where I encountered the same error.

Now I don’t need to comment out the fontDir.enable = true; to build correctly.