My Raspberry Pi 4 (8GB) model just came last week and after completing my RADIO (VMware's R&D Innovation Offsite) session recording, I wanted to setup my new rPI so I can start playing with it when I had some spare time. I also have the 4GB model but it was running quite hot as I was using the default case (do not recommend) and decided to put that aside for now. I ended up purchasing the 8GB model from Canakit which includes additional heatsinks and nice built-in fan with their custom case.
Look who just arrived to join the rest of 🥧 family! This will be my reward for tomorrow after I finish my #RADIO session recording pic.twitter.com/h9kxWRpM8S
— William Lam (@lamw.bsky.social | @*protected email*) (@lamw) July 1, 2020
After spending some time setting up the rPI OS and applying the various updates, I was not too keen on using the SD Card, especially as some folks on forums mentioned that it can easily be worn out depending on the type of workload. While researching online and some references pointed out by colleagues, I came to learn that in addition to booting from USB which is now possible with rPI, you can also network boot the rPI without an SD Card or any storage for that matter! This immediately resonated with me, especially as I am a huge fan of scripted installations such as Kickstart/Jumpstart.
Here are all the resources that I had used that provided all the heavy lifting. I have optimized some of the commands to make it easy for anyone to simply copy and past who is new to setting up an rPI. The authors below did a fantastic job in outlining all the details, so I highly recommend a read if you would like to get more information. I also will be going over an alternative method at the end for booting the rPI over the network which is not really talked about.
- https://hackaday.com/2019/11/11/network-booting-the-pi-4/
- https://www.ferdinand-keil.com/network-booting-rpi4-from-centos7.html
- https://codestrian.com/index.php/2020/02/14/setting-up-a-pi-cluster-with-netboot/
- https://linuxhit.com/raspberry-pi-pxe-boot-netbooting-a-pi-4-without-an-sd-card/
One really cool thing that I came to learn while setting up the infrastructure to network boot an rPI was the use of dnsmasq, which I have used in the past but I did not realize it could do so much more. I may have spent more time playing with dnsmasq than with the rPI itself and I will probably cover this in another blog post on how you can easily setup a PXE/gPXE/iPXE system to enable automated OS installation (e.g. Kickstart) that can be used with ESXi or any other OS for that support network installations via BIOS/UEFI.
Preparing the rPI
Step 1 - Download and install the Raspberry Pi Imager Tool for your OS
Step 2 - Plugin an SD Card (If the card is not formatted, you can use the Imager Tool to format) and then flash it with the rPI OS. Insert the SD Card and power up the rPI
Step 3 - Once rPI OS has booted up, open a terminal to enable SSH access and retrieve the IP Address assigned by running the following commands:
systemctl start ssh
ip add show eth0
Step 4 - SSH to the rPI using username pi/raspberry and then run the following command to update and upgrade the rPI
sudo apt-get update
sudo apt-get upgrade
Step 5 - Run the following command to download and apply the latest rPI BETA EEPROM which supports network booting. We are also updating the default boot order to 0xf241 which will try SD Card , USB and then Network Boot and then reboot to go through the boot order again.
PI_EEPROM_VERSION=pieeprom-2020-06-15
wget https://github.com/raspberrypi/rpi-eeprom/raw/master/firmware/beta/${PI_EEPROM_VERSION}.bin
sudo rpi-eeprom-config ${PI_EEPROM_VERSION}.bin > bootconf.txt
sed -i 's/BOOT_ORDER=.*/BOOT_ORDER=0xf241/g' bootconf.txt
sudo rpi-eeprom-config --out ${PI_EEPROM_VERSION}-netboot.bin --config bootconf.txt ${PI_EEPROM_VERSION}.bin
sudo rpi-eeprom-update -d -f ./${PI_EEPROM_VERSION}-netboot.bin
Step 6 - Lastly, we need to retrieve the rPI serial number and MAC Address which will be used
cat /proc/cpuinfo | grep Serial | awk -F ': ' '{print $2}' | tail -c 8
ip addr show eth0 | grep ether | awk '{print $2}'
Step 7 - Shutdown the rPI and remove the SD Card
Preparing the Kickstart/Netboot Server
Step 1 - Install an Ubuntu VM, I happen to have 16.04 lying around in my vSphere Datastore but you can use any recent version
Step 2 - Apply latest patches and install the following packages:
apt update
apt install -y nfs-kernel-server dnsmasq kpartx unzip
Step 3 - Download the latest rPI OS and run the following commands to prepare it so we can boot it over the network to our rPI:
wget -O raspbian_lite_latest.zip https://downloads.raspberrypi.org/raspbian_lite_latest
unzip raspbian_lite_latest.zip
kpartx -a -v *.img
mkdir {bootmnt,rootmnt}
mount /dev/mapper/loop0p1 bootmnt/
mount /dev/mapper/loop0p2 rootmnt/
Step 4 - Run the following command and replace it with your rPI serial (last 8 characters), MAC Address and the IP Address of your Ubuntu VM. This will create the necessary filesystem structure and copy the rPI OS from previous step to be able to boot the rPI over the network:
PI_SERIAL=abcdefgh
PI_MAC=dc:a6:ab:cd:ef:gh
KICKSTART_IP=192.168.30.176
mkdir -p /srv/nfs/rpi4-${PI_SERIAL}
mkdir -p /srv/tftpboot/${PI_SERIAL}
cp -a rootmnt/* /srv/nfs/rpi4-${PI_SERIAL}/
cp -a bootmnt/* /srv/nfs/rpi4-${PI_SERIAL}/boot/
Step 5 - We need to replace the default rPI firmware files with the latest version by running the following comamnds:
rm /srv/nfs/rpi4-${PI_SERIAL}/boot/start4.elf
rm /srv/nfs/rpi4-${PI_SERIAL}/boot/fixup4.dat
wget https://github.com/Hexxeh/rpi-firmware/raw/stable/start4.elf -P /srv/nfs/rpi4-${PI_SERIAL}/boot/
wget https://github.com/Hexxeh/rpi-firmware/raw/stable/fixup4.dat -P /srv/nfs/rpi4-${PI_SERIAL}/boot/
Step 6 - Next we setup the NFS export and dnsmasq configuration for the rPI to mount the images over the network. There are a number of dnsmasq configurations that you can tweak, but if you have an existing DHCP server and simply want to use it, simply specify your network broadcast address and "proxy" keyword as shown in the example below.
echo "/srv/nfs/rpi4-${PI_SERIAL}/boot /srv/tftpboot/${PI_SERIAL} none defaults,bind 0 0" >> /etc/fstab
echo "/srv/nfs/rpi4-${PI_SERIAL} *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
cat > /etc/dnsmasq.conf << EOF
dhcp-range=192.168.30.255,proxy
log-dhcp
enable-tftp
tftp-root=/srv/tftpboot
pxe-service=0,"Raspberry Pi Boot"
EOF
mount /srv/tftpboot/${PI_SERIAL}/
Step 7 - In addition to enable SSH and clearing the fstab file so it will not look for filesystem on the SD Card, the cmdline.txt is updated so rPI knows how to reach our NFS mount for serving the rPI OS image:
touch /srv/nfs/rpi4-${PI_SERIAL}/boot/ssh
sed -i /UUID/d /srv/nfs/rpi4-${PI_SERIAL}/etc/fstab
echo "console=serial0,115200 console=tty root=/dev/nfs nfsroot=${KICKSTART_IP}:/srv/nfs/rpi4-${PI_SERIAL},vers=3 rw ip=dhcp rootwait elevator=deadline" > /srv/nfs/rpi4-${PI_SERIAL}/boot/cmdline.txt
Step 8 - Enable and start the services
systemctl enable dnsmasq
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start dnsmasq
systemctl start rpcbind
systemctl start nfs-server
Step 9 - Finally, we are now ready to power on our rPI and you should see rPI OS boot over the network. You can also confirm things are working or debug by tailing the logs of /var/log/syslog on your Ubuntu system.
🥳 Just PXE Booted my rPI4!
Its a shame to enable PXE, you need to flash the EEPOM using rPI OS to change default which is to continuously try SDCARD (0xf34) pic.twitter.com/pAO4Nm02Ee
— William Lam (@lamw.bsky.social | @*protected email*) (@lamw) July 5, 2020
Alternative Network Boot on rPI
Thanks to fellow VMware colleague Andrei Warkentin, I came to learn about another method to network boot the rPI with other OSes that support PXE/iPXE is by using UEFI on the rPI itself via the SD Card which would enable you to boot anything you need over UEFI. The instructions below are additive and assumes you have completed the steps above already.
If you use UEFI in the Pi that *itself* supports PXE and HTTP booting (and also - iSCSI). Keep UEFI on SD and network boot whatever you need via UEFI.
— Andrei Warkentin (@WhatAintInside) July 5, 2020
Step 1 - Download the latest rPI Firmware and extract the contents to your computer, you should have a folder called firmware-master
Step 2 - Download the latest rPI 4 UEFI firmware and extract the contents to your compute you should have a folder called RPi4_UEFI_Firmware_v1.14
Step 3 - Delete all files starting with kernel*.img within firmware-master/boot directory and then copy the entire "boot" directory onto the newly formatted SD Card
If you're on MacOS system, the following commands can be used to perform the operation. In the example below, the SD Card label is called UEFI
rm ~/Desktop/firmware-master/boot/kernel*.img
cp -rf ~/Desktop/firmware-master/boot/* /Volumes/UEFI
Step 4 - Copy all files within the RPi4_UEFI_Firmware_v1.16 directory into the same boot directory on SD Card
If you're on MacOS system, the following commands can be used to perform the operation. In the example below, the SD Card label is called UEFI
cp -rf ~/Desktop/RPi4_UEFI_Firmware_v1.16/* /Volumes/UEFI
Step 5 - Eject the SD Card and plug that into your rPI
Step 6 - Update the /etc/dnsmasq.conf to include the following. In my example below, I am booting the netboot image for Ubuntu 20.04 AARCH64, but you should be able to specify any OS that supports UEFI booting on the rPI.
dhcp-match=set:aarch64,60,PXEClient:Arch:00011:UNDI:003000
dhcp-boot=tag:aarch64,ubuntu20.04/boot/bootnetaa64.efi
Note: If you want to boot rPI OS over the network, you will need to use the first option outlined. rPI OS does not used UEFI and hence you will not be able to use the alternative approach
Step 7 - Power on your rPI and you should see UEFI boot from the SD Card (rainbow screen) and then shortly after, you should see an image get served from the Kickstart/Netboot server.
mattm says
Now all we need is a way to PXE boot a rPI as a vSAN witness server 😉
Shane Gibson says
William - you might be interested in taking a look at the RackN "Edge Lab". It's a full automation system built on the Digital Rebar platform with Raspberry PI deployment/automation support. This method massively reduces the amount of manual work it takes to get Raspberry PI systems installed / automated and working in a useful manner. Check out our edge lab information and the digital rebar info at:
https://github.com/digitalrebar/edgelab
https://rackn.com/products/digitalrebar/
There are several videos referenced from the edge lab landing page too. We currently all play with 4-node RPi clusters on our desk ... and it works a treat !!
Steve Galbincea says
Looks like you can also network boot the rPI 3 as well. There goes my evening... 🤣
https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/net_tutorial.md
digitalfix says
Stumbling at the last step:
root@kickstart:/srv/tftpboot# systemctl start nfs-serverq
Failed to start nfs-serverq.service: Unit nfs-serverq.service not found.
William Lam says
Its "nfs-server", just fixed typo
Josh Solanes says
Hi William, thanks for your excellent guide! It helped me setup network booting with my Raspberry Pi 4 using a Gentoo Linux host with minimal changes.
The only changes I needed to make were:
In /etc/dnsmasq.conf, tftp-root needed to be /srv/tftpboot/${PI_SERIAL}
...Otherwise the Pi would fail to find elf files and would not continue
In /boot/cmdline.txt, ",proto=tcp" needed to be added to the end of the nfsroot param immediately after vers=3
With that, do you have any idea why I had the discrepancy in the dnsmasq.conf, and is there a way to specify certain IPs to use a certain tftp-root to support different Pis? I'd like to also network boot a Pi3B alongside the Pi4 with the same host and suspect they wouldn't share the same files in the tftp-root path
Josh Solanes says
I found a solution for dnsmasq to provide a separate tftp-root per machine!
https://stackoverflow.com/questions/40008276/dnsmasq-different-tftp-root-for-each-macaddress/51508180
Tom Shaw says
I am unable to get this to work with Ubuntu 20.04, following the second method I get left with just a grub console. The screenshot doesnt show it working, I get as far as the screenshot on Step 7. So what steps are required to make this work with Ubuntu 20 over UEFI in full? It surely must be possible to get Ubuntu running completely diskless.
Lars says
Great guide! Since I did not want to run an NFS server 24/7, I adapted the steps a bit so it only uses a TFTP and HTTP server while booting, and is independent of the network afterwards. I needed to swap to Alpine Linux to get that to work, but that's also a great and mature distro. I've documented the steps and created a script to automate all this here: https://github.com/biemster/rpi4_alpine_netboot
Marlon says
After booting up, my Pi4 display a black screen 🙁
With normal SD booting it works fine...
hedefalk says
Is there something wrong here:
mkdir -p /srv/nfs/rpi4-${PI_SERIAL}
mkdir -p /srv/tftpboot/${PI_SERIAL}
cp -a rootmnt/* /srv/nfs/rpi4-${PI_SERIAL}/
cp -a bootmnt/* /srv/nfs/rpi4-${PI_SERIAL}/boot/
The last one, is it supposed to be
cp -a bootmnt/* /srv/nfs/tftpboot/${PI_SERIAL}
?
Viktor Hedefalk says
Sorry, I think I was wrong here. I missed the mount thing later 🙂
hedefalk says
cat /proc/cpuinfo | grep Serial | awk -F ': ' '{print $2}' | tail -c 8
only gives me 7 numbers which I didn't notice until debugging dnsmasq log. I guess I get some right-padding or something? Anyways, with tail -c 9 I'm fine 🙂
BlueSpaceCanary says
I ran into this too. I checked the actual hex, and it looks like it's because `tail -c` includes the LF at the end of the line. `cat /proc/cpuinfo | grep Serial | awk -F ': ' '{print $2}' | tail -c 8 | xxd` (with the serial itself redacted here) gives me 00000000: XXXX XXXX XXXX XX0a XXXXXXX.
The last char in the hex is 0a (LF character) and the last character in the string representation is a . which is how xxd represents nonprinting characters
Ashley Oliver says
Is this part right?
```
Step 5 - ... updating the default boot order to 0xf241 which will try Network Boot, USB and then SD Card and then reboot to go through the boot order again.
```
The documentation (https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711_bootloader_config.md) says that the boot options are tried lowest nibble to highest nibble so 0xf421 would be try SD first then USB then net? 0xf142 would match the text.
William Lam says
Ashley,
Thanks for the note and you're correct. I actually had this at one point but must have forgotten and ended up correcting it for another article. I've gone ahead and updated the order
Alain Culos says
This tutorial looks fantastic, thank you.
I have a conundrum to solve though. I use raspberry pi zeros (plain, not wireless) with a USB ethernet dongle.
Unfortunately all have the same MAC address, which means that I have to set a different MAC address for each by altering the file "/etc/systemd/network/00-default.link".
How does this play with step 4 in the "Preparing the Kickstart/Netboot Server" section?
I presume the MAC address here must be the dongle's MAC address, but with several raspberry pis with the same dongle, does all having the same MAC and changing the MAC address interfere with this setup, or is the key bit of information the serial number?
Is there any other configuration to worry about because of the change of MAC address during boot?
William Lam says
No, it’s the serial as mentioned in blog post 🙂
Alain Culos says
Thank you & indeed, sorry I had scan-read a bit too fast.
rourke says
Hey quick question, what is sed -i /UUID/d /srv/nfs/rpi4-${PI_SERIAL}/etc/fstab supposed to do, right now I've gotten almost everything working except running into a small kernel panic after it starts booting.
I know the file doesn't change when I run it, any chance you have an example on what it does or how its supposed to look?
Thanks for the article.
Francis Augusto Medeiros-Logeay says
Great guide! I wonder if it is possible to extend this further to get a menu so that one could choose which OS to boot.
William Lam says
That's a great exercise for the reader 🙂
Francis Augusto Medeiros-Logeay says
I was so afraid that this would be the answer... 🙈😅
Francis Augusto Medeiros-Logeay says
This guide was pretty inspiring, so I used it as basis for booting off a FreeNAS and without needing to deal with dnsmasq: https://francisaugusto.com/2021/Booting-Pi-From-FreeNAS/
Corentin Dupont says
This line is not clear for me:
echo "/srv/nfs/rpi4-${PI_SERIAL}/boot /srv/tftpboot/${PI_SERIAL} none defaults,bind 0 0" >> /etc/fstab
Why mounting one folder over another? Why not just a link (ln -s ...)?
Corentin Dupont says
Also, is Step 5 really necessary?
rm /srv/nfs/rpi4-${PI_SERIAL}/boot/start4.elf
rm /srv/nfs/rpi4-${PI_SERIAL}/boot/fixup4.dat
wget https://github.com/Hexxeh/rpi-firmware/raw/stable/start4.elf -P /srv/nfs/rpi4-${PI_SERIAL}/boot/
wget https://github.com/Hexxeh/rpi-firmware/raw/stable/fixup4.dat -P /srv/nfs/rpi4-${PI_SERIAL}/boot/
The lastest RPI ISO should already have the latest firmware files, no?