I’ve come a long way since my last post in 2016. There’s a lot to write about. Let’s start by showing how a recent obsession of mine, applying Nix to every project, has finally spread to this very blog.

I have been using Nix/NixOS a lot. I like being able to capture a complicated, environment-specific setup process in a single command. I like being able to make patches to any software, and do so with a remote buildbot rather than my tiny Chromebook. It has gotten to the point where the dotfiles (and in some cases, entire operating systems) for every device I own is stored in a single git repo.

Now, each of my projects have a complete, portable, version-controlled, easy-to-use, and language-agnostic method to build it or set up its dev environment, without distro-specific dependency fetching or home directory cruft.

This site uses Jekyll. Before long, it, too, was being built via Nix. Here’s how it works.

Jekyll is a Ruby program. Any plugins are specified in the Gemfile. For this site, that’s github-pages, jekyll-feed, and jemoji. Nix can store gems, but for that to happen, each gem in the dependency tree needs to be known and content-addressable at eval time. The Gemfile.lock does not store hashes, so there is a tool that generates a Nix expression from the Gemfile, and the entire deptree will be available at eval time. I run nix run 'nixpkgs#bundix' -- -l which generates a gemset.nix file.

The flake.nix file is the topmost Nix expression. I define two packages, perrycode and perrycode-watch. They are both derivations with a single output each, but the former yields a directory containing the generated site, and the latter yields a shell script that wraps jekyll serve.

Now, I can run nix build to generate the site, and nix run to host it locally, watching for changes. The cool part is that this works on any machine that has Nix installed, regardless of distro, even WSL.

If I ever run into a problem where nokogiri (or some other troublesome gem) needs a C source patch to work with new versions of glibc (just a hypothetical, but a plausible one), it’d just be a six-line change, at most.

In the future, I would like to see Nix replace all language-specific package managers. Nobody likes solving a problem by deleting node_modules, re-running npm install, and hoping for the best.