Network Booting Raspbian Lite to a Raspberry Pi 4 from a Synology NAS

Work Environment

NAS: Synology DS216+II with DSM 6.1.7-15284

Netgear WNDR3700v2 Router Running Gargoyle Firmware version 1.10.0 or DD-WRT v3.0-r40559 std (08/06/19)

Raspberry Pi

Before you begin

If you have a battery backup unit then enable UPS.

To boot a Raspberry Pi 4 using PXE, there are a few steps required, starting with updating that bootloader firmware. This means installing Raspbian to an SD card and booting the Pi off of it at least once. From there, we turn to the PXE server to build the remote filesystem and set up the NFS and dnsmasq services. This article draws from a pair of official Pi network boot guides.

Bootloader Update

At the time of writing, the eeprom firmware that supports PXE boot is still in beta. We have to grab that firmware, change the boot order configuration, and then flash it to the onboard chip. Once the Pi 4 is booted off your Raspbian SD card, we can do the following to get the firmware updated:

$ sudo apt-get update
$ sudo apt-get upgrade
$ wget https://github.com/raspberrypi/rpi-eeprom/raw/master/firmware/beta/pieeprom-2019-10-16.bin
$ rpi-eeprom-config pieeprom-2019-10-16.bin > bootconf.txt
$ sed -i s/0x1/0x21/g bootconf.txt
$ rpi-eeprom-config --out pieeprom-2019-10-16-netboot.bin --config bootconf.txt pieeprom-2019-10-16.bin
$ sudo rpi-eeprom-update -d -f ./pieeprom-2019-10-16-netboot.bin
$ cat /proc/cpuinfo

That last command should output some information on the Pi itself. We’re interested in the entry for the Pi’s serial number. Write down the last 8 characters of that code, as we’ll use it later. That’s all the setup needed for the Pi itself.

Download Raspbian Lite ZIP file and extract the image.

If your router acts as the DHCP server in your network then it will need to support network booting (most do not) if you want to continue to use it as the DHCP server, otherwise you will need to disable DHCP on your router and setup a DHCP server on your NAS. An alternative is to install a Linux firmware to your router if it’s possible (i.e. OpenWRT, DD-WRT, etc.) which is the scenario used for this guide.

Synology Setup

Enable TFTP service on your NAS. (Control Panel -> File Services -> TFTP) and select a root folder to use for network boot files. (i.e. shared folder called “public” with a folder inside called “pxeboot”.)

Enable NFS service on your NAS. (Control Panel -> File Services -> SMB/AFP/NFS). Now click on “Shared Folder” and select the network share that you chose for network booting (i.e. “public”) and click the “Edit” button. Choose the NFS Permissions tab and click on the “Create” button. Use the following rules:

Hostname or IP: X.X.X.0/24 (Replace X.X.X with your local network)
Privilage: Read/Write
Squash: No Mapping
Security: sys

Make sure the box is ticked for “Enable asynchronous”, “Allow connections from non-privilaged ports (ports higher than 1024)”, and “Allow users to access mounted subfolders”, then click on the “OK” button. Click on the “OK” button to enable NFS on the selected share. From a Linux computer, test that the NFS share is now working (i.e. Try to access “nfs://synology/volume1/public”). If you are unable to access the NFS share from another computer on your network, then this issue will need to be resolved first before continuing.

Create a folder under the root folder used for network boot files (i.e “pxeboot”) with the serial number of the pi that you wrote down earlier.

Now have a look inside the partition table that you just extracted.

$ fdisk -l 2017-09-07-raspbian-stretch-lite.img 
Disk 2017-09-07-raspbian-stretch-lite.img: 1.7 GiB, 1854590976 bytes, 3622248 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
                                ^^^-----<<< write this down! <<<-------
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x11eccc69

Device                           Boot Start  End      Sectors Size Id Type
2017-09-07-raspbian-stretch-lite.img1 8192   93813    85622   41.8M c W95 FAT32 (LBA)
2017-09-07-raspbian-stretch-lite.img2 94208  3622247  3528040 1.7G 83 Linux
                                      ^^^^^-----<<< and these! <<<-------

In the output of fdisk -l you see some important information. We need to know the offset where the partitions start. To get this offset you simply multiply the sector size (usually always 512 bytes) with the start sector of the partition (both are marked above). Now do the following for both partitions.

Let’s create a loopback device with this information so we can mount it and steal the data from it.

$ sudo losetup -f --show -o $((512*8192)) 2017-09-07-raspbian-stretch-lite.img 
/dev/loop1

You need to be root to create loopback devices. -f found us a free loop device, -o took the offset we calculated and –show made sure we get to know which loop device losetup used. Now we can go and mount it like any other partition.

$ mkdir /tmp/fresh-pi-boot
$ sudo mount -v /dev/loop1 /tmp/fresh-pi-boot
mount: /dev/loop1 mounted on /tmp/fresh-pi-boot.
$ cd /tmp/fresh-pi-boot
$ ls
bin boot dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var

Now let’s copy that data to your NFS share. Replace [synology] with the IP address of your Synology NAS and [serial] with the serial number of your Raspberry Pi that you wrote down earlier.

$ mkdir /tmp/boot
$ sudo mount [synology]:/volume1/public/pxeboot/[serial] /tmp/boot
$ sudo rsync -Phax --numeric-ids /tmp/fresh-pi-boot/ /tmp/boot/

When it’s done, repeat the above steps for the rootfs partition which can be stored in a folder called “rootfs” under the serial folder of the pi on the NAS. There are about 31.000 files to copy, so this might take a while. Go brew some coffee or grab a beer.

So your NAS should now have the boot files in a folder named wih the serial number of your pi and also a folder named rootfs that contains the rootfs of Raspbian Lite. Next we need to edit some files:

/volume1/public/pxeboot/[serial]/cmdline.txt

dwcotg.lpm_enable=0 console=serial0,115200 console=tty1 elevator=deadline rootwait rw root=/dev/nfs nfsroot=[synology]:/volume1/public/pxeboot/[serial]/rootfs,v3,tcp ip=dhcp
/volume1/public/pxeboot/[serial]/rootfs/etc/fstab

[synology]:/volume1/public/pxeboot/[serial]   /boot   nfs defaults,vers=3,proto=tcp 0   0
none            /tmp            tmpfs   defaults        0       0
none            /var/run        tmpfs   defaults        0       0
none            /var/lock       tmpfs   defaults        0       0
none            /var/tmp        tmpfs   defaults        0       0

Next, reboot and the pi should now network boot to Raspbian Lite and you should be prompted with a login. Login with the default pi user account and create a new user. Then install Cinnamon Desktop and reboot.

$ sudo systemctl mask rpi-eeprom-update
$ sudo dpkg-reconfigure locales
$ sudo dpkg-reconfigure keyboard-configuration
$ sudo dpkg-reconfigure tzdata
$ sudo apt-get update && sudo apt-get -y upgrade && sudo apt-get -y dist-upgrade
$ sudo apt-get install xserver-xorg cinnamon-desktop-environment lightdm synaptic firefox-esr thunderbird hplip-gui
$ sudo adduser [username]
$ sudo usermod -aG sudo [username]
$ sudo reboot

I came across an issue with the audio stuttering. The following file edit fixed the problem:

$ sudo nano /etc/pulse/default.pa

Find the line that has the following:
load-module module-udev-detect

Modify it to:
load-module module-udev-detect tsched=0

Ctrl + O to save
A quick reboot and this fixed the issue (for me at least).