Raspberry Pi 3/4 mittels PXE vom Netzwerk booten

In diesem Artikel habe ich zusammen gefasst, wie ich meine Rasperry Pi's davon überzeugt habe, dass sie vom Netz booten sollen. Ich halte von SD-Karten nicht sonderlich viel, da sie je nach Qualität die Tendenz haben früher oder später kaputt zu werden. Ganz ohne geht es vielleicht gar nicht, wenn man etwa einen Rasperry Pi 3 verwendet. Dazu später mehr.

Weil ich leider alles was ich mir erarbeitet habe auch mindestens genauso schnell wieder vergesse, habe ich mich dazu entschieden, den gesamten Vorgang hier zu dokumentieren, um später ein Nachschlagewerk zu haben, falls ich einmal einen Fehler suchen oder einen zusätzlichen Raspberry Pi mit Netzwerk-Boot einrichten muss.

Die Voraussetzungen im Netzwerk werden hier nur kurz angeschnitten.

Netzwerk

Ich verwende im Netzbereich hauptsächlich Unifi Komponenten von Ubuquiti. Das Herzstück bildet eine UDM Pro, weiters sind einige Switches und WLAN-Router verbaut. Für das Booten vom Netz wird ein TFTP-Server und ein NFS-Server benötigt.

Um in den UDM Pro Settings PXE Boot zu aktivieren muss beim betroffenen Netzwerk die Option "DHCP Network Boot" aktiviert und entsprechend konfiguriert sein:

Hier ist jeweils die IP-Adresse des Servers bzw. der Name des Boot-Images anzugeben.

Wie man einen TFTP-Server bzw. NFS-Server installiert, werde ich hier nicht besprechen, dazu gibt es genug Doku im Netz. Wichtig ist bei meiner Konfiguration, dass das TFTP-Root-Verzeichnis und das freigegebene NAS-Share auf das selbe Verzeichnis zeigen (in meinem Fall ist das /mnt/nas). Andernfalls wird die nachfolgende Beschreibung nicht funktionieren und es müssten entsprechende Anpassungen vorgenommen werden.

Raspberry Pi 4

Zuerst wird das gewünschte Image mit dem Raspberry Pi Imager auf eine SD Karte geschrieben. Ich verwende Raspberry Pi OS Lite (64-bit), also ohne Desktop, da ich auf einem Server keine grafische Umgebung benötige. In den Optionen kann auch gleich der richtige Hostname eingetragen, SSH aktiviert und das Passwort für den User Pi gesetzt werden. Wenn das Image geschrieben wurde, die SD Karte in den Pi einlegen und booten.

Um die aktuellsten Updates zu installieren führt man

sudo apt-get update && sudo apt-get upgrade

aus.

Mittels sudo raspi-config wird in den Advanced Options auf die Verwendung des neuesten Bootloaders umgeschaltet (Latest). Die anschließende Frage, ob die Settings für den Bootloader auf die Default-Werte zurück gesetzt werden sollen, habe ich bejaht. Um den Bootloader zu aktualisieren (falls ein Update ansteht), muss der Raspi rebootet werden.

Nun müssen wir die ID des Raspberry Pi ermittlen, dies geschieht mit folgendem Kommando:

vcgencmd otp_dump | grep 28: | sed s/.*://g

Der Befehl sollte eine ID in folgendem Format ausgeben:

36f73078

Diese ID wird für die Folder am NFS-Server verwendet. Zuerst wird der Ordner für das Root-Filesystem angelegt:

pi@nfs-server:/mnt/nas $ mkdir /mnt/nas/rpi4-36f73078

Nun wechselt man wieder auf den Raspberry Pi 4 und mounted das Share. Dazu wird am ein Ordner unter /mnt angelegt:

sudo mkdir /mnt/nfs

Das NFS-Share wird in den eben angelegten Ornder mit folgendem Befehl eingehängt: 

sudo mount -t nfs -o nfsvers=3 192.168.225.10:/mnt/nas /mnt/nfs/ -vvv

Anschließend wird das komplette Root-Verzeichnis ("/") mit allen Subfoldern und Files auf das NFS-Share kopiert:

sudo rsync -xa --progress --exclude /mnt/nfs / /mnt/nfs/rpi4-36f73078/

Jetzt ist ein guter Zeitpunkt einen Kaffee oder ein kühles Blondes zu genießen, das Kopieren nimmt schon eine gewisse Zeit in Anspruch. Wenn der Kopier-Vorgang abgeschlossen ist, kann man mittels

ls /mnt/nfs/rpi4-36f73078/boot

feststellen, dass der Folder "boot" leer ist. Damit der Raspberry Pi 4 von TFTP-Server booten kann, muss das boot-Verzeichnis ins TFTP-Root Verzeichnis kopiert werden. Damit es nicht doppelt vorhanden ist, werden wir es in das Root-Filesystem kopieren und am TFTP-Root Folder mit einen symbolic Link arbeiten (wir erinnern uns: TFTP-Root = NFS-Share). Zuerst kopiert man also das Boot-Verzeichnis in das Root-Filesystem auf den NAS-Server:

sudo rsync -xa --progress /boot /mnt/nfs/rpi4-36f73078/

Nun sollten die Files korrekt vorhanden sein, eine kurze Kontrolle kann nicht schaden:

ls /mnt/nfs/rpi4-36f73078/boot

Auf dem TFTP/NFS-Server legen wir nun einen symbolic Link an (TFTP-Root = NFS-Share), der auf das Boot-Verzeichnis im Root-Filesystem zeigt:

pi@nfs-server:/mnt/nas $ ln -s rpi4-36f73078/boot/ 36f73078

Der Folder "36f73078" ist jener Ort, wo der Raspberry Pi 4 sein Boot-Image suchen wird.

Das TFTP-Root-Verzeichnis bzw. das NAS-Share sollten dann etwa wie folgt aussehen:

pi@nfs-server:/mnt/nas $ ls -al
drwxrwxrwx 6 root root 4096 Feb 11 01:00 .
drwxr-xr-x 3 root root 4096 Oct 10 16:52 ..
lrwxrwxrwx 1 pi pi 19 Feb 11 01:00 36f73078 -> rpi4-36f73078/boot/
drwxr-xr-x 18 pi pi 4096 Sep 22 05:06 rpi4-36f73078

Jetzt kann bereits die file system tab für den Raspberry Pi4 geändert werden, damit das Root-Filesystem vom NFS-Server anstelle von der SD-Karte gemountet wird.

pi@nfs-server:/mnt/nas $ sudo nano rpi4-36f73078/etc/fstab

Die bestehenden Einträge werden mit einem vorgestellten "#" auskommentiert oder gelöscht, und der neue Eintrag für "/" hinzugefügt. Das sollte dann so aussehen:

pi@nfs-server:/mnt/nas $ cat rpi4-36f73078/etc/fstab
proc /proc proc defaults 0 0
192.168.225.10:/mnt/nfs/rpi4-36f73078 / nfs defaults,noatime 0 1
#PARTUUID=0dbcbea5-01 /boot vfat defaults 0 2
#PARTUUID=0dbcbea5-02 / ext4 defaults,noatime 0 1

Als nächstes müssen die Start-Parameter im cmdline.txt geändert werden, um den Boot vom Netzwerk zu ermögichen:

pi@nfs-server:/mnt/nas $ sudo nano /mnt/nas/rpi4-36f73078/boot/cmdline.txt

Die Eintrag wird wie folgt geändert:

console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.225.10:/mnt/nas/rpi4-36f73078,nfsvers=3 rw ip=dhcp rootwait elevator=deadline

Jetzt muss als letzter Schritt noch der Netzwerk-Boot aktiviert werden. Dies geschieht wieder mit dem Befehl sudo raspi-config, dort im Menü Advanced Options/Boot Order den Network Boot auswählen. Danach muss der Raspberry Pi 4 noch einmal von der SD Karte gebootet werden damit die Einstellung wirksam wird. Sobald der Raspi hochgefahren ist, kann er wieder niedergefahren und die SD Karte entfernt werden.

Nun sollte der Raspberry Pi vom Netzwerk booten.

Raspberry Pi 3

Der Raspberry Pi3 kann leider nicht direkt vom Netz booten, daher wird immer eine SD-Karte für den Bootvorgang benötigt. Ich habe mir dafür billige kleine SD Karten (8 GB) besorgt. Kosten nur ein paar Euro. Das Root-Filesystem kann aber sehr wohl auf den NFS-Server gelegt werden. Somit können die Zugriffe auf die SD Karte auf ein Minimum reduziert werden.

Auch hier beginnen wir wieder mit dem Schreiben des OS Image auf die SD Karte . Ich verwende wie gesagt Raspberry Pi OS Lite (64-bit), also ohne Desktop, da ich auf einem Server keine grafische Umgebung benötige. In den Optionen kann auch gleich der richtige Hostname eingetragen und das Passwort für den User Pi gesetzt werden. Wenn das Image geschrieben wurde, die SD Karte in den Pi einlegen und booten.

Mittels sudo raspi-config wird als erstes der SSH Server aktiviert (Interface Options/SSH), damit remote via SSH auf den Pi zugegriffen werden kann.

Nun müssen wir die ID des Raspberry Pi ermittlen, dies geschieht mit folgendem Kommando:

vcgencmd otp_dump | grep 28: | sed s/.*://g

Das Kommando sollte eine ID in folgendem Format ausgeben:

fee2c58f

Am NFS-Server wird nun der Folder für das Root-Filesystem angelegt:

mkdir /mnt/nfs/rpi3-fee2c58f

Am NFS-Server sollte dies nun so aussehen (Achtung: hier sind auch die Einträge für den vorher bereits konfigurierten Raspberry Pi 4 sichtbar!):

pi@nfs-server:/mnt/nas $ ls -al
drwxrwxrwx 6 root root 4096 Feb 11 01:00 .
drwxr-xr-x 3 root root 4096 Oct 10 16:52 ..
lrwxrwxrwx 1 pi pi 19 Feb 11 01:00 36f73078 -> rpi4-36f73078/boot/
drwxr-xr-x 18 pi pi 4096 Sep 22 05:06 rpi3-fee2c58
drwxr-xr-x 18 pi pi 4096 Sep 22 05:06 rpi4-36f73078

Damit ist alles vorbereitet und es kann wieder auf den Raspberry Pi 3 gewechselt werden. Dort muss ein Folder angelegt werden, in den das NFS-Share in weiterer Folge gemountet wird:

sudo mkdir /mnt/nfs

Das NFS-Share mit folgendem Befehl mounten: 

sudo mount -t nfs -o nfsvers=3 192.168.123.15:/mnt/nas /mnt/nfs/ -vvv

komplette SD Karte auf das NFS Share kopieren:

sudo rsync -xa --progress --exclude /mnt/nfs / /mnt/nfs/rpi3-fee2c58/

Anschließend habe ich die Daten der VFAT-Partition (die Partition wird später in den Ordner /boot gemounted) auf eine billige 8 GB SD-Karte kopiert.

In der cmdline.txt auf der 8 GB SD-Karte muss dem Raspberry Pi 3 nun bekannt gemacht werden, dass er das Root-Filesystem vom Netzwerk mounten soll. Dazu tragen wir folgende Zeile in das cmdline.txt ein:

console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.225.10:/mnt/nas/rpi3-fee2c58,nfsvers=3 rw ip=dhcp rootwait elevator=deadline

Nun wird die Filesystem Tab am NFS-Server anpasst, damit das Root-Filesystem am NAS gemountet wird. Zusätzlich wollen wir auch noch die VFAT Partition nach /boot mounten, damit Updates für selbige beim Update-Vorgang auch korrekt installiert werden können:

sudo nano /mnt/nfs/rpi3-fee2c58/etc/fstab

Folgende Einträge müssen erzeugt werden:

/dev/mmcplk0p1                      /boot vfat defaults         0 2
192.168.123.15:/mnt/nfs/rpi-fee2c58 /     nfs  defaults,noatime 0 1

Die vorhandenen Einträge (PARTUUID=...) sind auszukommentieren oder zu löschen, das sollte dann etwa so aussehen:

Der Raspberry Pi sollte nun vom Netzwerk booten.

WICHTIG!

Falls einmal die Firmware des Switch aktualisiert werden muss, dann sollten zovor die vom Netz bootenden Raspis unbedingt niederfahren werden, sonst zieht man ihnen den Boden unter den Füßen weg! Es ist durchaus denkbar, dass das Filesystem dadurch eventuell Schaden nehmen könnte.

Quellen/hilfreiche Artikel:
https://rob-ferguson.me/how-to-pxe-boot-your-rpi/