Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Raspberry Pi with read-only file system

Raspberry Pi with read-only file system

Raspbian Buster Lite edition

Here are some very basic steps to make a Raspbian Lite installation read-only (stateless, volatile). This saves write cycles on the SD card and allows the Raspberry Pi to be powered off without shutdown.

Prepare the system

This guide is based on a fresh Raspbian Buster Lite (tested on version June 2019) installation.

Disable swap file

While disabling swapping is not a good idea in general, in a read-only environment there is no writable device for swapping.

dphys-swapfile swapoff
dphys-swapfile uninstall
systemctl disable dphys-swapfile.service

Remove unwanted packages

Log files are going to be stored on a temporary file system, so they do not need to be rotated. fake-hwclock tries to store the time in a file, which is undesirable in this case.

apt-get remove -y --purge logrotate fake-hwclock

Disable apt activities

Disable automatic upgrades and manpage cache creation.

systemctl disable apt-daily-upgrade.timer
systemctl disable apt-daily.timer
systemctl disable man-db.timer

Move resolv.conf to /run

resolv.conf is the only file in /etc that needs to be modified (assuming DHCP is used for nameserver discovery). It needs to be moved to a location that is writable (/run is a tmpfs) and readable by other processes (/tmp is not a good location because it may be masked for some services using PrivateTmp by systemd).

mv /etc/resolv.conf /run/resolvconf/resolv.conf
ln -s /run/resolvconf/resolv.conf /etc/resolv.conf

Enable tmpfs /tmp and /var/tmp

These directories need to be writable, with specific permissions. /var will be tmpfs anyway, so only the permissions need to be adjusted.

For /tmp the systemd supplied mount unit can be enabled.

echo -e "D /tmp 1777 root root -\nq /var/tmp 1777 root root -" > /etc/tmpfiles.d/tmp.conf
cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount

Clean up /var

These files are not needed anymore, so before mounting the temporary file system /var can be cleaned up to save some space on the SD card.

rm -rf /var/cache/apt /var/cache/debconf /var/lib/apt/lists

Enable read-only mode

Adjust kernel command line

Add this to the kernel command line (/boot/cmdline.txt). fsck on boot and swap are disabled, the root file system is mounted read-only, and systemd.volatile enables a temporary /var mounted on top of the read-only root.

fsck.mode=skip noswap ro systemd.volatile=state

Edit the file system table

Add the ro option to the file systems in /etc/fstab:

sed -i -e 's/vfat\s*defaults\s/vfat defaults,ro/' /etc/fstab
sed -i -e 's/ext4\s*defaults,noatime\s/ext4 defaults,noatime,ro/' /etc/fstab

Disable read-only mode

Reverse the modifications in /boot/cmdline and /etc/fstab from the above steps and reboot.

Issues

  • This is not easy to reverse. Install and configure packages and services before executing these steps.

  • As /var is volatile, there is no way of making the system read-write without a reboot. It might be possible to only mount some of /var as tmpfs, but services in general assume /var to be writable, so this has to be done with extra care.

  • /var will be empty on reboot. Services that need some kind of state from /var need to be reconfigured to get it from somewhere else. APT will not work, as the package database is also affected by this.

  • Time is received using NTP via systemd-timesyncd on reboot. Until the correct time is received, a (very) wrong time is used, e.g. in the boot log.

Ideas

  • systemd 242 (not provided in Raspbian Buster) will feature a more capable systemd.volatile=overlay setting that automatically mounts / as an overlayfs. This improves compatibility with services that are not aware of read-only file systems, but also has to be used carefully (e.g. writing lots of data to the in-memory overlayfs quickly consumes all memory).

  • Making /var an overlayfs instead of tmpfs is possible, however needs some additional work on boot in order to create the overlayfs. This adds little benefit and would be obsolete once systemd 242 hits Raspbian.

References

@sunknudsen

This comment has been minimized.

Copy link

@sunknudsen sunknudsen commented Mar 3, 2021

Thanks for the amazing guide!

Would you happen to know how to make sure journaling is disabled so the SD card is never written to?

I am trying to put together a configuration that allows computing a consistent SHA512 hash of the whole SD card.

@nicokaiser

This comment has been minimized.

Copy link
Owner Author

@nicokaiser nicokaiser commented Mar 13, 2021

Thanks @sunknudsen! I'm not sure if systemd writes to the disk, but as the FS is mounted read-only, I guess it will not. The journaling can stay enabled, as all logging is done in-memory and everything that is written to the /var partition is a tmpfs.
But it'd be interesting if the SHA hash stays the same over time, maybe there are some kind of "last mounted at" flags or something... Please let me know if you find out something about this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment