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

Variations of the Range kata

In the languages I usually employ. The Range kata is succinct, bordering on the spartan in both description and requirements. To be honest, it's hardly the most inspiring kata available, and yet it may help showcase a few in…

via ploeh blog January 1, 2024

Some notes on NixOS

Hello! Over the holidays I decided it might be fun to run NixOS on one of my servers, as part of my continuing experiments with Nix. My motivation for this was that previously I was using Ansible to provision the server, but then I’d ad hoc installed a bunch…

via Julia Evans January 1, 2024

I found some of my first code! Annotating and reflecting on robotics code from 2009.

In high school, one of my teachers shattered my plans for my life, in the most beautiful way. Most of my life, I'd intended to become a math professional of some sort: a math teacher, when that was all I saw math for; an actuary, when I started to lear…

via blog January 1, 2024

Generated by openring