Installing Vanilla NixOS on a Raspberry Pi 4B with UEFI

Prev

2023-06-10
Part of the nixos-on-rpi series.

Next

In my last post, I installed NixOS on a Raspberry Pi 3B. I installed NixOS on an RPi 4B, this time using the Raspberry Pi UEFI firmware and a vanilla bootloader setup with systemd-boot instead of U-Boot, which is what’s included in the SD card images.

I’ll go through the process of installation step by step.

Update the EEPROM

The RPi 4 has an EEPROM containing the on-board bootloader code. That means that it can be updated – which isn’t the case for the older RPi’s like my RPi 3B. With recent enough versions of the EEPROM image, that on-board bootloader supports GPT partitioned SD cards. That’s great as we don’t have to put up with MBR shenanigans anymore. Note that those images are sadly closed-source.

I’m not exactly sure what “recent enough” means here (the release notes don’t mention adding GPT support anywhere), but if you run into problems during installation, you might want to try updating the EEPROM first.

I myself still had a working LibreELEC install on the Pi’s old SD card, which includes an EEPROM updater. With that I updated to the newest version before continuing just to be sure.

Preparing the SD Card

I started by partitioning my SD card exactly like I would an SSD for a normal installation on a PC, which means:

Raspberry Pi UEFI Firmware

When fiddling around with my RPi 3, I stumbled upon the great open-source Raspberry Pi UEFI firmware for the RPi 3 and for the RPi 4. For the RPi 3 I didn’t end up using that, because its on-board bootloader doesn’t support GPT disks and isn’t updatable like the RPi 4’s is. I described those problems in detail in that post.

Anyway, the RPi 4 does support GPT partitioned disks, and I loved the UEFI firmware when I tried it. It’s also available for the RPi 4, so I wanted to try it again. I downloaded the latest release and, following the instructions from there, I put the files on the ESP partition of the SD card. That was it, nothing more to do!

Just as before on the RPi 3, it just worked. Booting up the Pi now gives me a fully-fledged UEFI boot menu!

Note that the UEFI firmware does have some limitations due to its nature. E.g. as the RPi doesn’t have NVRAM, changes to UEFI variables from the OS are not persisted. Changes made from the boot menu are persisted, of course (due to the lack of NVRAM, on the SD card itself).

Installing NixOS

The installation itself is surprisingly easy with the UEFI firmware.

As I now had a normal boot menu supporting USB available, I could download the vanilla ARM ISO install image from the NixOS website and put it on a USB stick to boot from.

I could now install NixOS from a USB stick onto the SD card like I would on any normal PC, using an EFI-capable bootloader like systemd-boot (NixOS’s default IIRC) or GRUB. And – it just works! No need for weird Pi-specific boot stuff here. The only thing we have to be careful about is the hardware config – see the following section.

Other than on my RPi 3 before I had no problem using my NixOS flake directly, it evaluated and built fine and in a reasonable timeframe. I didn’t have to bother with copying over the system closure via nix copy and SSH during the installation as detailed in the RPi 3 article.

Note that copying over the system closure wouldn’t even work, because while the RPi SD image has the Nix store on a plain ext4 root partition on the card, the ISO install image has the store on an overlayfs with very limited space. I actually tried to do nix copy at first, but ran out of space in the store. When you run nixos-install, the derivations are downloaded/built directly on the disk you’re installing onto, which circumvents the space problem.

What I would love to be able to do is install NixOS onto the SD card from my desktop, so I can then just put the SD card into the Pi, boot it, and have it work with my config. However, the last time I tried that, nixos-install didn’t seem to like being run from another system arch. I might look into that again some time, though. Maybe I can build SD card images with my config and an UEFI bootloader like the pre-built NixOS RPi images, maybe with nixos-generators?

Hardware Config

There are some caveats concerning the NixOS hardware config, though. Originally, I started off with the instructions from nix.dev, which uses the RPi 4 hardware config from the nixos-hardware repo. I included that in the config during installation – and it didn’t work.

I’m not the first one to run into that problem: there’s an issue in nixos-hardware already open. Seems to be a problem that started with NixOS 23.05.

The good thing is that the extra config from nixos-hardware doesn’t seem to be necessary at all anymore, according to a comment by Nebucatnetzer in the issue.

According to that comment, all we need are some additional kernel modules in boot.initrd.availableKernelModules:

boot.initrd.availableKernelModules = [
	"usbhid"
	"usb_storage"
	"vc4"
	"pcie_brcmstb" # required for the pcie bus to work
	"reset-raspberrypi" # required for vl805 firmware to load
];

So I removed nixos-hardware again, added those modules to my config, ran nixos-install – and it worked! The Pi boots and works fine. I opened an issue for nix.dev to improve the documentation there.

I have yet to try whether a graphical desktop, audio, video acceleration, etc. also work out of the box, I’ll update the article once I do.

Note that nixos-generate-config doesn’t include those initrd kernel modules. If they actually are required for the Pi to boot and work, which I haven’t tried myself, nixos-generate-config should detect that. Currently, it only links to nixos-hardware. I’ll experiment a bit more with what modules are required for what and then open an issue.

All in all: if the module detection issue is sorted out, we could do a NixOS installation following the normal NixOS installation instruction on a RPi using the UEFI firmware, which I think is really cool!

By the way, my current config for my RPi 4 can be found here: https://git.eisfunke.com/config/nixos/-/blob/main/devices/amethyst.nix


Thank you for reading!

Follow me on Mastodon / the Fediverse! I'm @eisfunke@inductive.space.

If you have any comments, feedback or questions about this post, or if you just want to say hi, you can ping me there or reply to the accompanying Mastodon post!