Calling extra initrd binary from initrdRules udev rule

My encrypted luks volume includes its own GPT partition table, so I need to run kpartx on it after encryption to map the partitions as their own block devices. It took me a bit of staring at stage-1.nix to figure out how to do so, so I’m posting the two needed lines here in hopes it helps someone else.

The first part is to include kpartx in the initramfs using extraUtilsCommands:

boot.initrd.extraUtilsCommands = "copy_bin_and_libs ${pkgs.multipath-tools}/sbin/kpartx";

This results in kpartx and its needed libs being included in the initramfs’s extra-utils package. The trickier part was figuring out how to call it from a udev rule, since it will live at, e.g., nix/store/j39ip29q1psb0j64sm2lpxzqhriv6pnz-extra-utils/bin/kpartx, where the hash will change from build to build. I finally figured out that the generated package can be found at config.system.build.extraUtils, and thus the following will work to call it at the correct path:

services.udev.initrdRules = ''ACTION!="remove", ENV{ID_PART_TABLE_UUID}=="ae2a115f-0d22-408d-8392-e2701348515b", RUN+="${config.system.build.extraUtils}/bin/kpartx -u /dev/$kernel"'';
2 Likes

I realized that in this particular case, I can just use boot.initrd.luks.devices.<name>.postOpenCommands to run kpartx, but hopefully this will still be useful for someone else for other use cases.

1 Like