Skip to main content

Installing NixOS on the Raspberry Pi 4 with UEFI and ZFS

·4 mins

After spending some time with OSMC on my Raspberry Pi 4, I’ve been meaning to install NixOS on it as it has been my distribution of choice on all my other systems.

Installing “vanilla” NixOS on the Pi isn’t too difficult, just follow the installation steps on the wiki: download the SD card image, decompress it, flash the image to the SD card and you’re good to go.

However, it gets more complicated when you try to go off the beaten path, such as when trying to do full-disk encryption or using filesystems other than ext4.

After some reading and some trial and error, here are the steps I took to get NixOS with ZFS on the Pi, with UEFI booting.

Requirements #

Make sure you’ve enabled support for USB booting on your Raspberry Pi. If yours is considerably older, you might need to update its EEPROM before you can enable support for USB booting. For more details, check the documentation.

Installation steps #

I started by booting the Pi off of a USB stick with the generic SD card AArch64 image but it would work just as well by initially booting off of an SD card.

As my installation target was a SATA SSD, I now connected it to one of the USB 3.0 ports on the Pi. I find using the Raspberry Pi with an SSD makes it feel more like a real computer, as the SSD is faster, has more storage capacity and will most certainly be more durable than a flimsy SD card, especially now that I’ll also be using the Pi as a home server.

Partitioning #

wipefs -a /dev/sda

parted -a optimal /dev/sda -- mklabel gpt
parted -a optimal /dev/sda -- mkpart ESP fat32 1MiB 513MiB
parted -a optimal /dev/sda -- set 1 esp on
parted -a optimal /dev/sda -- mkpart primary linux-swap 513MiB 8705MiB
parted -a optimal /dev/sda -- mkpart primary 8705MiB 100%

mkfs.fat -F 32 -n boot /dev/sda1

mkswap -L swap /dev/sda2
swapon /dev/sda2

zpool create -O mountpoint=none -O atime=off -o ashift=12 -O acltype=posixacl -O xattr=sa -O compression=zstd -O dnodesize=auto -O normalization=formD zroot /dev/sda3
zfs create -o refreservation=1G -o mountpoint=none zroot/reserved
zfs create zroot/root

mount -t zfs -o zfsutil zroot/root /mnt
mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot

UEFI setup #

We’ll now setup UEFI on the Pi. We do this by placing the files from the Raspberry Pi 4 UEFI Firmware Images on the boot partition:

nix-shell -p wget unzip
cd /mnt/boot
wget https://github.com/pftf/RPi4/releases/download/v1.33/RPi4_UEFI_Firmware_v1.33.zip
unzip RPi4_UEFI_Firmware_v1.33.zip
rm README.md
rm RPi4_UEFI_Firmware_v1.33.zip

2022/11/04 Update: As a reader pointed out, you can also do this step by just copying the files on the installation media (assuming /dev/sda is your installation disk):

mkdir /firmware
mount /dev/sda1 /firmware
cp /firmware/* /mnt/boot

NixOS installation #

As per usual, we let NixOS generate a config for us:

nixos-generate-config --root /mnt

As we’re using ZFS, we’ll need to enable ZFS support:

boot.supportedFilesystems = [ "zfs" ];
networking.hostId = "<8 random numbers>";

And also specify the zfsutil mount option for each of our datasets (in the /mnt/etc/nixos/hardware-configuration.nix file):

  fileSystems."/" = {
    device = "zroot/root";
    fsType = "zfs";
    options = [ "zfsutil" ];
  };

Now, as we’re booting with UEFI, we’ll delete the following line which is generated by default:

boot.loader.generic-extlinux-compatible.enable = true;

…and we’ll install a UEFI bootloader:

boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.enable = true;

Finally, we’ll install NixOS:

nixos-install

Closing remarks #

To my surprise, I found that by using UEFI I could more easily achieve non-standard setups with NixOS on the Pi. I had some attempts at trying to install NixOS with ZFS with the usual booting setup on the Pi but I could never seem to boot it after the installation.

I should also note that setting up encryption and remote unlocking is not very difficult on this setup, as it only requires a little bit more of ZFS configuration.

After setting this up, a friend of mine pointed me to the following links:

It turns out that I accidentally ended up building an ARM system which is aligned with the NixOS ARM lead’s view for NixOS ARM systems in the future, which I find amusing.

References #