NixPI

Updated: March 13, 2025

Setting up NixOS on a Raspberry Pi with netboot from Synology Nas via Unifi.


Table of Contents

Gather information and write down the last 8 characters

We will be using these serials for the subdirectory names of our TFTP server.

cat /proc/cpuinfo | grep Serial

# this will print off only the 8 needed characters
vcgencmd otp_dump | grep 28: | sed s/.*://g

Prepare Netbooting

Use RaspberryOS to setup settings in the firmware if ≤ pi3
We can check bootloader config with vcgencmd bootloader_config
as well as version with vcgencmd version

# get latest software and upgrade
sudo apt update && sudo apt upgrade -y

# update the eprom
sudo rpi-eeprom-update -d -a

# reboot to apply update
sudo reboot

# set boot order is our main task here
sudo -E rpi-eeprom-config --edit

This will present the defaults of config file we want:
Change TFTP_IP to IP of TFTP Server on your network.
Change BOOT_ORDER to 0x214
POWER_OFF_ON_HALT to 1

[all]
BOOT_UART=0                 # 0: Disable Serial Port 1: Enable Serial Port
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=1         # 0: Stays On 1: Turn Off after shutdown
DHCP_TIMEOUT=45000
DHCP_REQ_TIMEOUT=4000
TFTP_FILE_TIMEOUT=30000
TFTP_IP=192.168.1.87        # IP of TFTP Server
TFTP_PREFIX=0
BOOT_ORDER=0x214            # 1: SD 2: Netboot 4: USB 8: NVMe 0: Stop Sequence f: Restart Sequence (loop) 
[none]
FREEZE_VERSION=0            # 0: Updatable 1: Frozen

Reboot to apply changes

sudo reboot       # sudo shutdown -r now

Check everything is alright with vcgencmd bootloader_config
If all is well, shutdown and repeat whole process on the next pi.

sudo shutdown -h now

Create SDcard NixOS Image

This will need to be built on a machine that has NixOS and if
the machine is different architecture it will need to be cross-compiled.
The end output should be nixos-sd-image-25.05-aarch64-linux.img
Best to create a git repository for use in generating the images.
It doesn’t need everything, just to get started with NixOS, after boot
we can then start a new repo for the pi to be managed with.

# configuration.nix
{ config, pkgs, ... }:

{
  imports = [
    <nixpkgs/nixos/modules/installer/sd-card/sd-image-aarch64.nix>
  ];
  networking.hostName = "nixos-pi"; # Customize per Pi if desired
  services.openssh.enable = true;
  users.users.root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3Nza... " ]; # Replace with your public key
  networking.useDHCP = true; # Or set static IPs if preferred
  # Add other desired settings (e.g., packages)
}

Install nixos-generators if you do not have it as this will be used to build the image:

nixos-generate -f sd-aarch64 -I nixpkgs=channel:nixos-unstable -c configuration.nix

TFTP Server

This is the protocol that utilizes the boot portion of the image.
We need to create a shared folder to then place inside our serial subdirectories.

  1. Create TFTP shared root folder (tftpboot)
  1. Create serial subdirectories
  1. Enable TFTP service

NFS Shares for Root Filesystems

This will need top level folder for each pi.

  1. Create NFS Shared Subdirectories for each Pi
  1. NFS Settings: Control Panel > Shared Folder > Edit > NFS Permissions

Populate NFS Shares

Move boot files to tftp and root files to nfs.

  1. On the build machine mount the image we created earlier.
sudo losetup -f --show -P nixos-sd-image-*.img  # Outputs e.g., /dev/loop0
sudo mkdir -p /mnt/boot /mnt/root ~/boot-template
sudo mount /dev/loop0p1 /mnt/boot               # Boot partition
sudo mount /dev/loop0p2 /mnt/root               # Root partition
sudo cp -r /mnt/boot/* ~/boot-template
  1. Copy boot files to tftp

cmdline.txt

ro nfsroot=192.168.1.87:/mnt/nfsshare/nixos-root-filesystem,v3 root=/dev/nfs rootwait elevator=deadline systemd.debug_shell=1 systemd.log_level=info disable_splash earlyprintk=serial,ttyS0,115200 initcall_debug printk.time=1 console=tty1 console=serial0,115200n8 init=/sbin/init loglevel=8