npins + colmena personal configuration

Inspired by various blog posts, amongst which Jade’s Pinning NixOS with npins, or how to kill channels forever without flakes, I decided to migrate my Flake-based configuration, which included nixosConfigurations, Home Manager homeConfigurations, system-manager systemConfigs, and a devShell, away from Flakes and to npins. I don’t claim that this is inherently better than Flakes, but it was an interesting process and I think I learned some things working on it.

One npins feature I was particularly interested in is the ability to follow the tags of a Git repository. A Flake can only follow a ref (which can be a tag, but doesn’t automatically update). It’s also interesting to be able to follow a nixpkgs channel instead of the corresponding Git branch, though that doesn’t seem to have any observable effects.

If you want to follow along at home, the last Flake-based commit is last-flake.

Rather than the wrapper-script approach described by Jade, I decided to use colmena to deploy NixOS systems. While I’m gaining experience with tools, I might as well gain experience with two tools at once.

System Configurations

Before I started the conversion, I did some general cleanup. For example, I switched from the Lix overlay module to using the Lix included in nixpkgs so I could take advantage of Hydra builds.

I started by migrating the nixosConfigurations to colmena. This was pretty straightforward. The only thing that tripped me up is that colmena checks for the presence of flake.nix to decide if it should use Flakes or not, so I renamed my flake.nix so I could have it for reference during the conversion and have colmena read from hive.nix.

In the initial conversion, I lost only nix-index-database since I couldn’t immediately figure out how to reference its home-manager module without going through the flakes interface.

Initially, I tried to configure cross compilation for my Raspberry Pi. Unfortunately, this basically requires building everything since I can’t take advantage of Hydra builds, so I switched to using buildOnHost = true. That was faster even though I end up building some software on the Pi since most of the software is available from the cache. The ideal thing would be if I had a more powerful aarch64-linux machine, I could configure it as a remote builder and do the builds there, but I don’t have one.

While writing this blog post, I tried building the configuration for the Pi under emulation but not cross compiling. This worked, and did substitute most of the configuration, and it’s slightly faster than building directly on the Pi, so I’m going to leave that in place for now.

Home Manager

Home manager was a little harder. When not running in Flake mode, the home-manager command uses <nixpkgs> and <home-manager> from NIX_PATH. I used the wrapper script approach described by Jade to have these reference the proper pinned values.

system-manager

On my work laptop, which runs Linux but not NixOS, I was using system-manager to set up GPU drivers for Nix-built software. When I first did this conversion, there was no documented way to use system-manager without Flakes, and I didn’t look into it. When I came back a few weeks later, system-manager had had modifications that simplified using the Nix components without Flakes, though still no documentation. The system-manager command still assumes Flakes, but I was able to write a shell script that uses raw Nix commands to build, register, and activate the system-manager configuration.

nix-index-database

nix-index-database is also designed to be consumed as a Flake. It has a default.nix that provides the wrapped packages, that works fine, but the Home Manager module is provided as a functor that expects the Flake (self) as the argument. Even so, we have all the tools available to make this work. I wrote this adapter module:

{ pkgs, ... }:
let
  sources = import ../../npins;
  packages = (import sources.nix-index-database) { inherit pkgs; };
  dummyFlake = {
    packages.${pkgs.stdenv.system} = packages;
  };
  hmModule = (import "${sources.nix-index-database}/home-manager-module.nix") dummyFlake;
in
{
  imports = [ hmModule ];
}

I read the home manager module functor to figure out what attributes were needed, which turns out just to be the packages for the current system. It re-imports the npins sources since using the sources that I provided through extraSpecialArgs caused an infinite recursion error.

And there you have it: a Flake-free pinned configuration for all the things.

links

social