Running a Raspberry Pi 4 with NixOS

For quite some time I’ve been wanting to run a small homelab with NixOS. I don’t host much services myself, however I feel that I can have a lot of fun (and learn a bit) by maintaining my own server. All the services I run on the Cloud™ (Matrix Dendrite and a Nix Binary Cache) could be running on a Raspberry Pi inside my drawer. So that be it!

A picture of Raspberry Pi inside an Argon One case and a Keychron K2V2
A picture of Raspberry Pi inside an Argon One case and a Keychron K2V2 (full size)


At the time of writing my setup looks like this:


Download the NixOS aarch64 image. Personally I went with the unstable branch as I like to live dangerously but you can choose other versions if you want to. After that you just need to dd it to your flash drive and boot it:

$ sudo dd if=nixos.img of=/dev/sdX bs=4096 conv=fsync status=progress



You can actually follow the NixOS Manual to partition your hard drive. However I’ve written a script to help me do this:

# replace /dev/sda with your SSD
export FMT_DISK=/dev/sda

wipefs -a $FMT_DISK

export DISK=/dev/disk/by-id/ata*

parted $FMT_DISK -- mklabel msdos
parted $FMT_DISK -- mkpart primary fat32 0MiB 512MiB # $DISK-part1 is /boot
parted $FMT_DISK -- mkpart primary 512MiB -4GiB # $DISK-part2 is the ext4 partition
parted $FMT_DISK -- mkpart primary linux-swap -4GiB 100% # Swap

mkfs.ext4 -L nixos $DISK-part2
mount $DISK-part2 /mnt

mkfs.vfat -F32 $DISK-part1
mkdir -p /mnt/boot
mount $DISK-part1 /mnt/boot

NixOS Configuration

In order to boot correctly, you need to define some boot options1:

  boot = {
    initrd.availableKernelModules = [ "usbhid" "usb_storage" ];
    kernelPackages = pkgs.linuxPackages_rpi4;
    kernelParams = [

    loader = {
      raspberryPi = {
        enable = true;
        version = 4;

      grub.enable = false;
      generic-extlinux-compatible.enable = true;

  hardware.enableRedistributableFirmware = true;

Boot firmware

The installer disk has a partition containing the necessary firmwares to boot (it was on /dev/sda1/ for me). Just copy it to your boot partition.

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


With Channels

The only step left is to install the system:

nixos-install --root /mnt

With Flakes

Another way to install it is to make use of Nix Flakes. This way we can ensure that our build is completely reproducible and/or running the same software version as the other machines.

This is a rather simple process if you already have a repo configured with your NixOS configurations. First, I need a shell with git and a Nix version that supports the experimental Flakes commands.

nix-shell -p git nixUnstable

After that I just clone my repository, copy the hardware-configuration.nix file over and install the system.

# clone the repository
git clone
cd dotfiles

# copy hardware-configuration.nix
cp /mnt/etc/nixos/hardware-configuration.nix hosts/rpi4/

# install the system
nixos-install --flake .#rpi4

Articles from blogs I follow around the net

The four tenets of SOA revisited

Twenty years after. In the January 2004 issue of MSDN Magazine you can find an article by Don Box titled A Guide to Developing and Running Connected Systems with Indigo. Buried within the (now dated) discussion of the technology…

via ploeh blog March 4, 2024

Building a demo of the Bleichenbacher RSA attack in Rust

Recently while reading Real-World Cryptography, I got nerd sniped1 by the mention of Bleichenbacher's attack on RSA. This is cool, how does it work? I had to understand, and to understand something, I usually have to build it. Well, friends, that is what…

via blog March 4, 2024

How to unbreak Dolphin on SteamOS after the QT6 update

A recent update to Dolphin made it switch to QT6. This makes it crash with this error or something like it: dolphin-emu: symbol lookup error: dolphin-emu: undefined symbol: _Zls6QDebugRK11QDockWidget, version Qt_6 This is fix…

via Xe Iaso's blog March 3, 2024

Generated by openring