{"id":23594264,"url":"https://github.com/pexmor/raspi-netboot","last_synced_at":"2026-04-26T22:31:15.077Z","repository":{"id":172673624,"uuid":"483556939","full_name":"PexMor/raspi-netboot","owner":"PexMor","description":"Raspberry Pi network boot","archived":false,"fork":false,"pushed_at":"2022-04-25T16:44:04.000Z","size":23,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-17T14:09:25.136Z","etag":null,"topics":["dhcp","nfs","raspberrypi","tftp"],"latest_commit_sha":null,"homepage":"https://pexmor.github.io/raspi-netboot/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PexMor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-20T07:46:18.000Z","updated_at":"2022-04-20T13:30:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"8b716313-323b-4217-bffe-5e29a5af006a","html_url":"https://github.com/PexMor/raspi-netboot","commit_stats":null,"previous_names":["pexmor/raspi-netboot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PexMor/raspi-netboot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PexMor%2Fraspi-netboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PexMor%2Fraspi-netboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PexMor%2Fraspi-netboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PexMor%2Fraspi-netboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PexMor","download_url":"https://codeload.github.com/PexMor/raspi-netboot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PexMor%2Fraspi-netboot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32315711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T21:09:39.134Z","status":"ssl_error","status_checked_at":"2026-04-26T21:09:21.240Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dhcp","nfs","raspberrypi","tftp"],"created_at":"2024-12-27T09:16:27.745Z","updated_at":"2026-04-26T22:31:15.070Z","avatar_url":"https://github.com/PexMor.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Netboot Raspi\n\nThis document gather some notes on how to setup booting a Raspberry Pi (3B+ and later) over network.\n## The process\n\n1. U-Boot on RPi waits 10s before trying the DHCP (?speedup by boot order?)\n2. DHCP IP requests is sent over to DHCP server (target address is 255.255.255.255 - IPv4 broadcast, IPv6 is available starting RPi 4B+)\n3. DHCP server reponds with IPv4 and few more options (43,66,67 - where only the `66`/next-server is required)\n4. RPi using the option `66` requests `bootcode.bin`\n5. The `bootcode.bin` is executed and extra files are requested from `TFTP` server\n6. When all files are \n\n### Files requested on RPi 3B+\n\nThe following was recorded by `tftpd-hpa` daemon on Ubuntu 20.04. Some files are listed and requested __twice__ and not all files are present in `boot.tar.xz` or `BOOT`/FAT partition on your micro SD card or image.\n\n\u003e Note: the `\u003cserial\u003e` is placeholder for actuall serial number of your RPi.\n\nThe whole process spans across period of aprox. 3 seconds running on 1Gbps network (though RPi 3B+ has USB LAN chip capable of ~ 300Mbps).\n\nFor details see [#Boot folder](https://www.raspberrypi.com/documentation/computers/configuration.html#the-boot-folder) and/or [Raspberry Pi](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-4-boot-eeprom)\n\n| filename                             | status        |\n|--------------------------------------|---------------|\n| `bootcode.bin`                       | ok            |\n| `bootsig.bin`                        | not present   |\n| `\u003cserial\u003e/start.elf`                 | ok            |\n| `\u003cserial\u003e/start.elf`                 | ok#2          |\n| `\u003cserial\u003e/autoboot.txt`              | not present   |\n| `\u003cserial\u003e/config.txt`                | ok            |\n| `\u003cserial\u003e/recovery.elf`              | not present#1 |\n| `\u003cserial\u003e/start.elf`                 | ok#3          |\n| `\u003cserial\u003e/fixup.dat`                 | ok            |\n| `\u003cserial\u003e/recovery.elf`              | not present#2 |\n| `\u003cserial\u003e/config.txt`                | ok#2          |\n| `\u003cserial\u003e/config.txt`                | ok#3          |\n| `\u003cserial\u003e/dt-blob.bin`               | not present   |\n| `\u003cserial\u003e/recovery.elf`              | not present#3 |\n| `\u003cserial\u003e/config.txt`                | ok#4          |\n| `\u003cserial\u003e/config.txt`                | ok#5          |\n| `\u003cserial\u003e/bootcfg.txt`               | not present   |\n| `\u003cserial\u003e/bcm2710-rpi-3-b-plus.dtb`  | ok            |\n| `\u003cserial\u003e/bcm2710-rpi-3-b-plus.dtb`  | ok#2          |\n| `\u003cserial\u003e/overlays/overlay_map.dtb`  | not present   |\n| `\u003cserial\u003e/overlays/overlay_map.dtb`  | not present#2 |\n| `\u003cserial\u003e/config.txt`                | ok#6          |\n| `\u003cserial\u003e/config.txt`                | ok#7          |\n| `\u003cserial\u003e/overlays/vc4-kms-v3d.dtbo` | not present   |\n| `\u003cserial\u003e/overlays/vc4-kms-v3d.dtbo` | not present#2 |\n| `\u003cserial\u003e/cmdline.txt`               | ok            |\n| `\u003cserial\u003e/cmdline.txt`               | ok#2          |\n| `\u003cserial\u003e/recovery8.img`             | not present   |\n| `\u003cserial\u003e/kernel8.img`               | ok            |\n| `\u003cserial\u003e/kernel8.img`               | ok#2          |\n| `\u003cserial\u003e/armstub8.bin`              | not present   |\n| `\u003cserial\u003e/kernel8.img`               | ok#3          |\n| `\u003cserial\u003e/kernel8.img`               | ok#4          |\n\nImportant files:\n\n`cmdline.txt` - points to the NFS and sets the kernel options including `splash` and `quiet` (ref.[conf/cmdline.txt.sample](conf/cmdline.txt.sample)) which could look like:\n\n`dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=100.64.0.1:/nfs/client1,vers=4.2,proto=tcp rw ip=dhcp rootwait elevator=deadline quiet splash`\n\n`config.txt` - the usual RPi config (as found on FAT `/boot` partition)\n\nfiles present in `boot.tar.xz`:\n\n```\nbcm2710-rpi-cm3.dtb\nbcm2710-rpi-zero-2.dtb\nbcm2710-rpi-zero-2-w.dtb\nbcm2710-rpi-2-b.dtb\nbcm2710-rpi-3-b.dtb\nbcm2710-rpi-3-b-plus.dtb\nbcm2711-rpi-cm4.dtb\nbcm2711-rpi-cm4s.dtb\nbcm2711-rpi-4-b.dtb\nbcm2711-rpi-400.dtb\ncmdline.txt\nconfig.txt\nCOPYING.linux\nfixup_cd.dat\nfixup.dat\nfixup_db.dat\nfixup_x.dat\nfixup4cd.dat\nfixup4.dat\nfixup4db.dat\nfixup4x.dat\nissue.txt\nkernel8.img\nLICENCE.broadcom\noverlays\nstart_cd.elf\nstart_db.elf\nstart.elf\nstart_x.elf\nstart4cd.elf\nstart4db.elf\nstart4.elf\nstart4x.elf\n```\n\nSome manapages (eventually search `man dnsmasq`):\n\n* [man dnsmasq](https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html) to provide DHCP, TFTP and DNS\n* [man rpcinfo](https://linux.die.net/man/8/rpcinfo) to list registered SUN RPC services\n* [man exportfs](https://linux.die.net/man/8/exportfs) re-export `-r` as root and show `-v`\n* [man tar](https://linux.die.net/man/1/tar)\n* [man losetup](https://man7.org/linux/man-pages/man8/losetup.8.html)\n* [man rsync](https://linux.die.net/man/1/rsync)\n\n## Install packages\n\n__Ubuntu server 20.04 LTS__\n\nas __root__ (`sudo -i`):\n\n```bash\napt install nfs-kernel-server dnsmasq tcpdump\n```\n\n```bash\ncat \u003e\u003e/etc/exports \u003c\u003cDATA\n/nfs *(rw,sync,no_subtree_check,no_root_squash)\n/tftp *(rw,sync,no_subtree_check,no_root_squash)\nDATA\n```\n\nTo list available SUN RPC services on local computer `rpcinfo`.\n\nRun the services:\n\n* `dnsmasq` provides the DHCP(68), TFTP(69) and DNS(53) services (ports)\n* `rpcbind` provides service 2 port mapping for SUN RPC\n* `nfs-kernel-server` is the file service (use of NFS v4.2 over TCP is recommended)\n\n```bash\n#\nsystemctl enable dnsmasq\nsystemctl restart dnsmasq\n#\nsystemctl enable rpcbind\nsystemctl restart rpcbind\n#\nsystemctl enable nfs-kernel-server\nsystemctl restart nfs-kernel-server\n#\nsystemctl enable nfs-server\nsystemctl restart nfs-server\n```\n\n* [prepare_pxetools.sh](https://datasheets.raspberrypi.com/soft/prepare_pxetools.sh)\n* [pxetools.py](https://datasheets.raspberrypi.org/soft/pxetools.py)\n\nTo get serial number `cat /proc/cpuinfo` which is then used in TFTP boot or can be observed in `dnsmasq` logs when enabled as file request path `.../\u003cserial-number\u003e/start4.elf`\n\n`${TFTP_ROOT}/bootcode.bin` is the bootcode downloaded by RPi __U-Boot__ from rom, which in turn loads the rest from `${TFTP_ROOT}/\u003cserial-number\u003e/...`\n\n* [Main download space @ downloads.raspberrypi.org](https://downloads.raspberrypi.org)\n* [raspios_lite_arm64/boot.tar.xz](https://downloads.raspberrypi.org/raspios_lite_arm64/boot.tar.xz) - extract to `${TFTP_ROOT}/orig`\n* [raspios_lite_arm64/root.tar.xz](https://downloads.raspberrypi.org/raspios_lite_arm64/root.tar.xz) - extract to `${NFS_ROOT}/orig`\n\n### To extract use tar with xattrs and acls\n\nThe boot partition of image [2022-04-04-raspios-bullseye-arm64-lite.img.xz](https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2022-04-07/2022-04-04-raspios-bullseye-arm64-lite.img.xz) to expand `unxz *.img.xz` and `kpartx -a *.img` to prepare loopbacks and which then can be mounted via `mount /dev/mapper/loopXpY` where __Y=1__ = `/boot` and __Y=2__ = `/`.\n\nOr use the pre-prepared __tar.xz__ note use GNU tar (BSD does not have all options, also MacOS X)\n\n[raspios_lite_arm64 @ RFP](https://downloads.raspberrypi.org/raspios_lite_arm64)/[boot.tar.cz](https://downloads.raspberrypi.org/raspios_lite_arm64/boot.tar.xz)\n\n```bash\nmkdir -p ${TFTP_ROOT}/orig\ntar -xvJ --xattrs --acls -f boot.tar.xz --directory=${TFTP_ROOT}/orig\n```\n\n[raspios_lite_arm64 @ RFP](https://downloads.raspberrypi.org/raspios_lite_arm64)/[root.tar.cz](https://downloads.raspberrypi.org/raspios_lite_arm64/root.tar.xz)\n\n```bash\nmkdir -p ${NFS_ROOT}/orig\ntar -xvJ --xattrs --acls -f root.tar.xz --directory=${NFS_ROOT}/orig\n```\n\n\u003e Note: __x__ - extract, __v__ - verbose, __J__ - use `unxz`, __directory__ - extract to this directory/folder \n\n### TFTP bootcode.bin\n\nThen copy `${TFTP_ROOT}/orig/bootcode.bin` to `${TFTP_ROOT}/bootcode.bin` to let the __U-Boot__ to find it.\n\n### TFTP per RPi\n\nThe rest of `${TFTP_ROOT}/orig/.` should be copied to per RPi sub-folder like `${TFTP_ROOT}/\u003cserial-number\u003e/`.\n\nMake a copy and __update__ `conf/cmdline.txt.sample` to `${TFTP_ROOT}/\u003cserial-number\u003e/` to __update__:\n\n`nfsroot=100.64.0.1:/nfs/client1` to reflect the roof filesystem path on NFS server.\n\nyou might add `quiet` and `splash` and eventually ``\n\nInstall splash screen (plymouth) `sudo apt -y install rpd-plym-splash` (ref.`plymouth.ignore_serial_console` see [rpi/issue](https://github.com/raspberrypi/documentation/issues/1234))\n\n* [RPi Chromium dashboard](https://gist.github.com/jordigg/30bf20eaa23f2746d9eb8eebd05fd546)\n* [Pi Kiosk](https://reelyactive.github.io/diy/pi-kiosk/)\n* [Web dashboard](https://fullstackcode.dev/2020/09/13/turn-your-raspberry-pi-into-web-dashboard/)\n* [Another dashboard](https://yyjhao.com/posts/raspberry-pi-web-dashboard/)\n* [RPi 4 wall dashboard](https://jonathanmh.com/raspberry-pi-4-kiosk-wall-display-dashboard/)\n* [OctoDash](https://github.com/UnchartedBull/OctoDash)\n* [Productivity dashboard](https://www.jlwinkler.com/2017-05-25/raspberry-pi-productivity-dashboard/)\n* understand [cmdline.txt](https://forum.manjaro.org/t/understanding-cmdline-txt-on-raspberry-pi-4-minimal-fresh-install-vs-xfce/80385)\n* [Raspberry Valley](https://raspberry-valley.azurewebsites.net/) - inspiration via [RPi Leds](https://raspberry-valley.azurewebsites.net/Raspberry-Pi-LEDs/)\n### NFS root per RPi\n\nThe root filesystem should be copied by `11-replicate_nfs.sh` for each client `rsync -av --info=progress2 --xattrs --acls \"${SRC_FS}/.\" \"${DST_FS}/\"`. Some experiments were done on using __overlayfs__ so far without success.\n\n* [Pi Server](https://www.raspberrypi.com/news/piserver/)\n* deprecated [Pi Net](http://pinet.org.uk)\n* [LTSP](https://ltsp.org) - linux terminal server project\n* Domoticz [OverlayFS](https://www.domoticz.com/wiki/Setting_up_overlayFS_on_Raspberry_Pi)\n* [Extended Attrs in NFS](https://www.phoronix.com/scan.php?page=news_item\u0026px=Linux-5.9-NFS-Server-User-Xattr)\n\n## Extra info\n\n__RPF__ = Raspberry Pi foundation\n\n* [Leds on raspi](https://raspberry-valley.azurewebsites.net/Raspberry-Pi-LEDs/#act-green)\n* [RPF docs on net boot](https://www.raspberrypi.com/documentation/computers/remote-access.html#network-boot-your-raspberry-pi)\n\n## Other commands\n\n### Configure NAT\n\n```bash\nsource ~/.config/raspi/netboot/config.inc\niptables -I FORWARD -i ${IF_NAME} \\! -o ${IF_NAME} -j ACCEPT\niptables -I FORWARD \\! -i ${IF_NAME} -o ${IF_NAME} -j ACCEPT\niptables -t nat -I POSTROUTING -s ${SUBNET} \\! -o ${IF_NAME} -j MASQUERADE\n```\n\n### Turn off swap\n\nSwap does not make much sense when RPi is netbooted\n\n```bash\n# as root \"sudo -i\"\nsync\nswapoff -a\napt-get purge -y dphys-swapfile\nrm /var/swap\nsync\n```\n\n### Mount bind\n\n```bash\nsudo mount --bind /mnt/nvme/nfs /nfs\n```\n\n### Stop rpcbind\n\nTo stop all the `rpcbind` service to port mapper (locking, fileserver, ...)\n\n```bash\n#\nsystemctl stop rpcbind\nsystemctl disable rpcbind\nsystemctl mask rpcbind\n#\nsystemctl stop rpcbind.socket\nsystemctl disable rpcbind.socket\n#\nsystemctl status rpcbind\n```\n\n## Where are the ips\n\nIn general it is recomended to use DNS (as [It's Always DNS](https://teeherivar.com/product/its-always-dns-sysadmin/))\n\n`address=/pi-server/192.168.x.y`\n\n| path                      | IP/DNS | Usage                                               |\n|---------------------------|--------|-----------------------------------------------------|\n| DHCP server option `66`   | IP/DNS | next-server pointing to `TFTP server`               |\n| tftp:`serial`/cmdline.txt | IP/DNS | NFS server IP or name, mount `/` aka root partition |\n| rootfs`@`nfs/etc/fstab    | IP/DNS | NFS server IP or name, mount `/boot` partition      |\n\n## DHCP proxy\n\n[DHCP Proxy explainer @ FOG](https://wiki.fogproject.org/wiki/index.php?title=ProxyDHCP_with_dnsmasq#How_ProxyDHCP_works)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpexmor%2Fraspi-netboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpexmor%2Fraspi-netboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpexmor%2Fraspi-netboot/lists"}