Several of our projects (£B Till Display, Watershed Signage) use a Raspberry Pi at their heart with multiple units that are nearly identical. In order to roll-out changes to all of them at the same time, we net-boot them – essentially the entire root-filesystem resides on another server that the Pi can access via NFS.
Step 1: The NFS-server
This is the most involved part and varies a little per operating system. There are plenty of guides on setting up an NFS-server, suffice to say that I’ll assume you have /exports/pi-root exported, read-only to the IP-address or subnet that your Pi will be on — also note that you should use no_root_squash or -maproot=root:wheel as appropriate.
The first thing to do is get a root filesystem. The easiest way to do this is to use the one on the Raspbian distribution’s “Raw Images”. Under Ubuntu, I just extracted it, worked out the partition start-point, mounted it via loopback and copied it verbatim:
unzip 2013-07-26-wheezy-raspbian.zip fdisk -lu 2013-07-26-wheezy-raspbian.img # Start is 122880, so offset is 122880 * 512 = 62914560 losetup -o 62914560 /dev/loop0 2013-07-26-wheezy-raspbian.img mount /dev/loop0 /mnt cp -rp /mnt/ /exports/pi-root/ umount /mnt losetup -d /dev/loop0
Next we need to stop the OS from obtaining a new DHCP lease. Fortunately, this is quite easy, simply edit /etc/network/interfaces and make eth0 static:
iface eth0 inet static
You’ll also want to remove/comment-out the existing entry in /etc/fstab for mounting /dev/mmcblk0p2 on /, since netbooting has provided it with a root filesystem. It’s often also a Good IdeaTM to mount /boot read-only to avoid SD-card corruption on quick, unclean reboots or power-cycling:
#/dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p1 /boot vfat defaults,ro 0 2 #/dev/mmcblk0p2 / ext4 defaults,noatime 0 1 /dev/nfs / rootfs defaults,ro 0 0
If you’re going to have several instances of Pis netbooting off the same image, you will want to make the NFS-export read-only. Unfortunately, many services will want to write things all over the disk — sometimes you will want to too. Fortunately, tmpfs comes to the rescue here. For example, to create /tmp using 10% of the available RAM and /var/log using 20%, add this to /etc/fstab.
tmpfs /tmp tmpfs nodev,nosuid,size=10%,mode=1777 0 0 tmpfs /var/log tmpfs nodev,nosuid,size=20%,mode=1755 0 0
Stop the boot-sequence whinging about /tmp being read-only before /tmp is mounted:
touch /tmp/.tmpfs
Step 2: DHCP
We’re using ISC-DHCPd, so we already have an IP-pool setup. All we do here is point the specific Raspberry Pi (identified by MAC-address) at the place on NFS server that it needs to use by adding this to our server’s dhcp.conf and restarting it:
host net-booting-raspberry-pi { hardware ethernet b8:27:eb:XX:XX:XX; # Change to match your Pi's MAC-address fixed-address A.B.C.D; # Optionally associate a specific IP-address with the Pi default-lease-time 115200; # Keep the lease around for a long while (32-hours) # The magic that sets what the Pi uses as its root filesystem option root-path "server:/exports/pi-root,tcp,vers=3"; }
Step 3: The Raspberry Pi
This is the easiest part. Simply add this to /boot/cmdline.txt:
ip=dhcp root=/dev/nfs nfs-options=hard,intr,ro
With all that done, any changes to the root file-system on the NFS-server are instantly propagated to all the client Pis; however, just to keep everything happy, we tend to reboot them nightly by adding a crontab entry:
30 5 * * * root /usr/sbin/reboot -dfn
Extras
Whilst developing the environment, I found it quite useful to NFS-export a duplicate of the /exports/pi-root (e.g. as /exports/pi-root-dev) to one specific Pi (via a tweaked DHCP entry) with read/write permissions; make changes like apt-get update dist-upgrade; and then copy the files back to /exports/pi-root for all the others to grab.
We’ve found that you can get a little more performance out of some setups by specifying the read- and write-sizes. We’ve added rsize=32768,wsize=32768 to the Pi’s DHCP root-path entry and tweaked the NFS-server and networking stack similarly. Again, these changes may/not help you and are operating system specific, so left as an exercise for the reader.
Update: if you want the kernel on a network too…
@barnoid writes to mention that U-Boot allows you to netboot the entire OS (although because of the Pi’s limitations, you still have to load the U-Boot code from an SD card). We haven’t played with this yet, though.
Great work.
NFS share must be similar to “/mnt/rootfs *(rw,no_root_squash)” in /etc/exports to prevent bad perms (and many services crash).
And we can add “/dev/nfs / rootfs defaults 0 0” to /etc/fstab (a little bit cleaner)
Hi alexalouit,
You’re quite right on both counts and I’ve updated the post to reflect that.
Thanks!
Stewart.