My goal was to use an old Pi 4 as a bluetooth speaker by pulseaudio-connecting it to my stereo server. I wasn't able to get NixOS to boot with working bluetooth, but raspbian-bullseye-2022-09-22 unsurprisingly works fine. I tried to use that, but found I've become incapable of using (or unwilling to use?) any non-nix Linux, so I started on this tool instead.
It's a NixOS with a specially hacked-in bootloader and kernel, taken verbatim from a working rasbian image. There are 2 derivations of interest:
- The
initial
configuration, which generates an image for the initial boot of the pi, intended to be copied to an SD card. - The
update
configuration, which generates a derivation used to update a pi which is running a NixOS previously generated byinitial
.
The intended usage is to build these things on some fast hardware, not the pi itself and not necessary aarch64, so some patching of nixpkgs to make things cross-compile has been and may still be necessary (typically this means disabling documentation, which tends to try to use binaries created by the build).
The update
system activation will never update the kernel or the bootloader.
Instead, the pi bootloader's cmdline.txt
points to a symlink /nixos-rpi-init
which is updated by the activation script.
Edit rpi4-configuration.nix
to fit your needs. Make sure you have SSH enabled
and that the pi will be reachable on your network. Then build the initial
derivation:
$ nix-build rpi4.nix --argstr hostName my-pi -A initial -o initial
$ sudo cp -a ./initial/sd-image/nixos-sd-image-21.11pre-git-aarch64-linux.img /dev/<sd card device node>
Put it into your pi and boot. To switch to a new configuration, build the
update
derivation:
$ nix-build rpi4.nix --argstr hostName my-pi -A update -o update
$ nix-copy-closure --to <pi address> ./update
$ ssh <pi address> $(readlink update)
- Should make it so that
update
can replace the/boot
and kernel/firmware with a new raspbian image. But it's not important: if you want to try a new raspbian, use it to generate a newinitialize
and go from there.
- The
btuart.nix
derivation is key: raspbian has/usr/bin/btattach
which presumably is run at startup to create the hci device. Here it's wrapped up in a systemdbluetooth-hciattach.service
which must beforking
and AFAIK cannot have be "undone" so stopping this service is not recommended. - I found that I had to use an older bluez version (bluez-5.55, which is what raspbian has) or else there would be errors on pairing, something about a missing info or keys file in the bluetooth /var state directory.