Read-only Root Filesystem

In my previous posts about ramdisks and persistent storage on my Raspberry Pi, I explained my goal to reduce write access to the sd card as far as possible.

The last step is to mount the sd card read-only, so its filesystems can almost never get damaged. This is the expected behaviour of most embedded devices. You can power-cycle them and do no damage to their internal storage.

First, you need to edit your /etc/fstab file to configure the root and boot filesystems to be mounted read-only. To do this, you change the option field (the 4th field) of the lines starting with /dev/mmcblk0p0 and /dev/mmcblk0p1 from defaults to ro:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    ro                0       2
/dev/mmcblk0p2  /               ext4    ro                0       1
tmpfs           /tmp            tmpfs   defaults,noatime,mode=1777      0       0
tmpfs           /var/log        tmpfs   defaults,noatime,mode=0755      0       0
tmpfs           /var/lock       tmpfs   defaults,noatime,mode=0755      0       0
tmpfs           /home/andreas/rrd       tmpfs   defaults,noatime,mode=0777      0       0

With the next reboot, both your root and boot filesystems are write-protected and cannot be modified by the system. In my case, I needed to do some more changes, so that all system services run without errors.

If you log in to your system and want to change something, e.g. change a configuration file, then you can re-enable the write access with the following command:

mount / -o remount,rw

and disable write access again with

mount / -o remount,ro

nginx

My raspberry is executing the nginx webserver to process and deliver some PHP files. The PHP scripts are processed by the FastCGI module of nginx. This module sometimes tries to create temporary files in /var/lib/nginx/fastcgi. To disable this, edit the /etc/nginx/nginx.conf file and add this line to the http-section:

fastcgi_temp_path  /tmp/fastcgi_temp 1 2;

Then all temporary files get stored in the /tmp directory mounted as a ramdisk.

fake-hwclock

The raspberry does not have a realtime clock. During startup it gets the current time and date by querying a NTP server. To prevent the time jumping back to start of 1970 if the ntp server does not answer (e.g. due to network problems), the file /etc/fake-hwclock.data is written once per hour with the current time. During startup this time is restored to the system.

My raspberry is always connected to the network, so I can disable the fake-hwclock mechanism. Simply comment out all lines in /etc/cron.hourly/fake-hwclock by prepending a # character. Then reload the cron configuration with

service cron reload

Persistent Ramdisk Storage

As described here, I use a ramdisk for working data which is regularly (once per night) and during shutdown backed up to the sd card. For this to work, I added two lines to the init script managing the backup which enables write access to the sd card, then does the backup and then disables write access again:

mount / -o remount,rw
rsync --quiet --archive --delete --recursive --force ${RAMDISK}/ ${PERSIST_STORE}
mount / -o remount,ro

This is a bit dangerous, because for a short time, the write access to the sd card is enabled and data is written. Only once per day and during shutdown. But it might happen that the power is switched off too early during shutdown and the filesystem could be damaged. Because of that I currently think about sending the ramdisk contents to another system over the network, so I never need to enable write access to the sd card.

sudo

Sudo tries to write a timestamp to the directory /var/lib/sudo everytime you use it. I have not yet found a solution to disable this, so sudo will print out an error message, but anyhow lets you execute your command under the root account.

logrotate

Logrotate is a tool to prevent logfiles from growing indefinitely. By default, every week it compresses the logfiles to gziped files and discards compressed files older than 4 weeks. Logrotate writes internal info to a state file which is stored under /var/lib/logrotate. To move this file to a writeable location, edit the cron script /etc/cron.daily/logrotate and add the option --state /var/log/logrotate.state:

#!/bin/sh

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate --state /var/log/logrotate.state /etc/logrotate.conf

man-db

Every week an index of the man pages installed on the raspberry is built. This does not work on a read-only filesystem, so I disabled it by adding the line exit 0 to the beginning of the scripts /etc/cron.weekly/man.db and /etc/cron.daily/man.db. This is no important change, but my raspberry keeps sending me mails as long as the man-db scripts fails to update the index.

Package Update Check

Here I described how the raspberry could automatically check for Raspbian updates. This also does not work on a read-only filesystem. As an intermediaty solution I added the mount / -o remount,rw and mount / -o remount,ro commands before and after the apt-get update call and run the script only once per week (sundays at 3am) to reduce the risk of damaging the filesystem. This is no optimal solution, but I have no better one yet.

LinkedIn logo mail logo