Skip to content

Installing NixOS on Raspberry Pi (ft. UEFI)

I have a Raspberry Pi that have been runing Debian for most of the time. But no longer! This is how I install NixOS on it. To make things even more fun (and easier), I'll use UEFI.

To legacy or not to legacy

Traditionally (and perhaps still officially) the only way one can put any OS on a Raspberry Pi is by flashing an image to an SD card. For NixOS, the image is typically a build of nixos.sd_image.aarch64-linux. This "legacy" method works well for simple use cases, but it have major drawbacks and will quickly fall short when more complicated setups are desired. One thing is that the disk layout is fixed, so / encryption is not possible. Specifically for NixOS, the image tries to accommodate many platforms, causing it hard to make changes for one platform while making others happy. The community have also planned to move away (see there for more discussion).

Introducing UEFI. With it, we can perform installation in a much more "familiar" way while avoiding the drawbacks of the legacy method. What's more, the Pi Firmware Task Force even provides prebuilt platform firmwares, saving us the hassle of building from EDK2 source.

Preparing installation medium

As with UEFI on x86_64, we need a NixOS installer ISO, which can be retrieved here. A build of platform firmware is also required.

Like the "legacy" method, we need to create a disk layout that the Raspberry Pi's bootloader recognize, which is MBR with a FAT32 partition of type 0c. Then we extract platform firmware and the installer files and fix GRUB configuration for it to find the disk.

sfdisk /dev/sda <<EOF
label: dos
type=0c
EOF
mkfs.vfat -n NIXOS /dev/sda1
mount -m /dev/sda1 root
bsdtar xf nixos-minimal-25.05beta738172.eb62e6aa39ea-aarch64-linux.iso -C root
unzip RPi3_UEFI_Firmware_v1.39.zip -d root
sed -i 's/nixos-minimal-25.05-aarch64/NIXOS/g' root/EFI/BOOT/grub.cfg

Finally, we sync writes and unmount the disk.

sync
umount root
rmdir root

Booting up and installing

My installation process is somewhat different than the general procedure. Instead of preparing a display and keyboard to do initial setup, I will use serial console. This means I need these two:

  • A dummy HDMI plug (NixOS installer won't boot without this)
  • A USB to UART bridge (for example CH340G)

Create the following wiring:

  • header GND to bridge GND
  • header GPIO14 (TXD) to bridge RXD
  • header GPIO15 (RXD) to bridge TXD

Make sure to also select 3.3V output if applicable.

Open a serial console with minicom, then power on the Raspberry Pi.

minicom -b 115200 -D /dev/ttyUSB0

Wait a few seconds,1 and we will see the UEFI prompt:

ESC (setup), F1 (shell), ENTER (boot)......

After that, this message will appear:

Loading graphical boot menu...

Press 't' to use the text boot menu on this console...

We don't use a display, so press T. Now we are at the GRUB menu, and we will go with the first one.

                             GNU GRUB  version 2.12

 /----------------------------------------------------------------------------\
 |*NixOS 25.05beta738172.eb62e6aa39ea Installer                               |
 | NixOS 25.05beta738172.eb62e6aa39ea Installer (nomodeset)                   |
 | NixOS 25.05beta738172.eb62e6aa39ea Installer (copytoram)                   |
 | NixOS 25.05beta738172.eb62e6aa39ea Installer (debug)                       |
 | HiDPI, Quirks and Accessibility                                            |
 | rEFInd                                                                     |
 | Firmware Setup                                                             |
 | Shutdown                                                                   |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 |                                                                            |
 \----------------------------------------------------------------------------/

      Use the ^ and v keys to select which entry is highlighted.
      Press enter to boot the selected OS, `e' to edit the commands
      before booting or `c' for a command-line.

After a short period of waiting, we are now logged in as nixos!

The next thing to do is to setup Wi-Fi with wpa_supplicant and set a password. We also take a note of the IP address.

sudo systemctl start wpa_supplicant.service
wpa_cli <<EOF
add_network
set_network 0 ssid "SSID"
set_network 0 key_mgmt WPA-PSK
set_network 0 psk "PSK"
enable_network 0
quit
EOF
passwd
ip address show dev wlan0

Now we need to prepare some files before we can install. Remember that for UEFI to work we need platform firmware, so we need to have a copy on the final SD card. We also need to extract host ssh key for sops-nix to decrypt secrets.

mkdir -p root/boot
unzip RPi3_UEFI_Firmware_v1.39.zip -d root/boot

mkdir -p root/etc/ssh
sops -d --extract '["pegasus-ssh-host-ed25519-key"]' --output root/etc/ssh/ssh_host_ed25519_key secrets.yaml
chmod 600 root/etc/ssh/ssh_host_ed25519_key

Finally, set disk encryption key and SSH password. Now we are ready to install.

nvim disk.key
read -s SSHPASS
export SSHPASS
nix run github:nix-community/nixos-anywhere -- \
  -f '.#pegasus' \
  --env-password \
  --disk-encryption-keys /tmp/disk.key disk.key \
  --extra-files root \
  --target-host nixos@10.0.2.15

After the Raspberry Pi reboots, enter disk pasword in the serial console. Wait a few more seconds and we are at the login prompt!