Booting Raspberry PI from a NFS Root
The microSD cards, in my opinion, arent devices made to be ON all the time. For that reason, I thought if the root file system was mounted somewhere else it could be possible to turn off the microSD card, just using it for booting purposes. That was my main objective.
In fact, remote file systems are supported for a while (at least 30 years..
according to [1]), including for booting purposes, for instance using root=/dev/nfs
in kernel arguments we make the root file system come from a NFS (Network File System).
Requirements
You do not need to follow exactly the steps as described here but these are the specs I’ve used in my environment.
To simplify, the latest raspbian Linux image can be used, however note that it uses 1.4GB just for the OS, meaning it’s a bit oversized for booting over the Internet. Building a root from stratch and adjust it to fit your needs could be the best (building the Raspbian kernel is already described in [2]).
A small sized SD card can be used in this case (I’d say 16MB is enough) and you don’t need to image it, in fact, I’ve used the SD card from my camera without removing the files. The size must be enough to have just the
/fat
partition files used in Raspbian (start.elf
,cmdline.txt
,kernel.bin
, etc.).The NFS server is necessary but it is also relatively easy to mount one (I give the instructions here for Debian distro).
We start by preparing the NFS server, then the RPI SD card.
NFS Server Preparation
The NFS Server will contain the root of the Raspbian Linux, this root contains etc
,
var
, home
and other paths including the kernel dynamic modules used. These
instructions are based in [3]. In server (Debian) install the packages
nfs-kernel-server
and portmap
.
# apt-get install nfs-kernel-server portmap
Make sure the server has network access to the RPI. It will use UDP ports to connect to
this server so in case you’re using it, adjust the firewall rules for that. To configure it
make sure /etc/defaults/portmap
file has the OPTIONS line commented. Add ALLOW rule for portmap
in hosts.allow and restart portmap.
# perl -pi -e 's/^OPTIONS/#OPTIONS/' /etc/default/portmap
# echo "portmap: 192.168.1." >> /etc/hosts.allow
# invoke-rc.d portmap restart
The portmap daemon is configured. For the NFS daemon we need to tell it to share a folder that
will have RPI root file system. I’ve chosen it to be located at /rpiroot
, then change NFS config.
# mkdir /rpiroot
# vim /etc/exports
Add the following line:
/rpiroot rpi_ip_address/rpi_net_mask(rw,no_root_squash,subtree_check)
If your RPI or NFS server are behind a NAT (as was my RPI..) an additional option is required:
insecure
so it becomes:
... (rw, insecure, no_root_squash, subtree_check) ...
You will see the following error in /var/log/syslog in those situations:
mountd[30142]: refused mount request from rpi_ip for
/rpiroot (/rpiroot): illegal port 57913
Then refresh the NFS daemon shares with:
# export.fs -ra
To test if it’s working OK, mount the share somewhere:
# mount your_nfs_IP:/rpiroot /mnt
If any error happens here, you should fix it before continue, otherwise RPI might not be able to boot.
Now download the latest Raspbian image and mount the root partition. To do that
you need to know where it starts in the image file, I’ll use parted
for that.
/root/ # mkdir rpi
/root/ # cd rpi
rpi/ # wget http://...raspberrypi.img
rpi/ # parted raspberrypi.img
(parted) unit
Unit? [compact]? B
(parted) print
Model: (file)
Disk /root/rpi/.....raspberrypi.img: ...B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File sy...
1 1048576B 79691775B 78643200B primary fat16...
2 <u>79691776</u>B 1802502143B 1722810368B primary ext4...
(parted) quit
rpi/ # mkdir rpi-root
rpi/ # mount -o offset=79691776 ...raspberrypi.img rpi-root
We now create a path where we want the root to be located in the server, (remember I’ve used
/rpiroot
, and copy all the root files in rpi-root
to there.
rpi/ # cp -varP rpi-root/* /rpiroot/
...(cp verbose output)...
We can unmount the image, but you can write down or copy_paste the start location of the FAT16 partition, we’re going to need that later. Now we’ve the NFS root ready, we just need to prepare the SD card for the RPI.
Prepare the SD Card
Mount the RPI image file you downloaded, we just need to access the first partition now. Using the start location of the FAT16 partition (1048576 in this case) do:
# mkdir rpi-img
# mount -o offset=1048576 ...raspberrypi.img rpi-fat
Plugin your SD card, if it didn’t mount it automatically, mount its FAT partition somewhere and copy the files from the image to there (replace /dev/sdb1 to the correct in your case):
# mkdir rpi-sdcard
# mount /dev/sdb1 rpi-sdcard
# cp rpi-img/* rpi-sdcard/
Now edit the cmdline.txt that should be inside the SD card and change/add the following arguments and leave the rest:
... root=/dev/nfs ip=dhcp nfsroot=your_nfs_ip:/rpiroot ...
You can configure the IP manually also, check Linux Kernel boot arguments for more info on that. The SD card and the image partitions can be unmounted now and you’re ready to test NFS root on RPI.
# umount rpi-sdcard
# umount rpi-img
Ready to Boot
Plug-in the SD card in RPI and make sure its net can reach the NFS server. I’d advice running a tcpdump at the NFS server and using a display on the RPI so you can see the console output and to better understand if something goes wrong.
Conclusions
Booting the Raspbian through a remote root file system has some advantages and drawbacks. As advantages are the unneed of imaging the SD cards and low usage of SD card. The drawbacks are that you need either a small Linux kernel or fast network connection, the disk write will be limited to 10MB/s and if you want to use swap the SD card (or USB drive?) should be used for that.
References
[1] http://www.ibm.com/developerworks/library/l-network-filesystems/index.html