This is part of a series of posts on the design and technical steps of creating Himblick, a digital signage box based on the Raspberry Pi 4.
Another nice to have in a system like Himblick is the root filesystem mounted readonly, with a volatile tempfs overlay on top. This would kind of always guarantee a clean boot without leftovers from a previous run, especially in a system where the most likely mode of shutdown is going to be pulling the plug.
This won't be a guarantee about SD issues developing over time in such a scenario, but it should at least cover the software side of things.
In theory, systemd supports this out of the box
with the systemd.volatile=overlay
kernel command line option, including
integrating this with journald and the way other things get mounted.
In practice:
- this feature is available starting from systemd 242 (Debian Buster has 241). Systemd 242 is however available from backports.
- Debian's default initrd, initramfs-tools, does not run systemd.
- dracut does, but Debian's dracut does not yet know how to include the relevant parts of systemd
- Raspbian doesn't boot with an initrd by default, althoug it can.
While things catch up, dracut has a rootovl
option that implements something
similar.
The procedure becomes, roughly:
# apt install --no-install-recommends dracut
# echo filesystems+=overlay > /etc/dracut.conf.d/overlay.conf
# dracut /boot/initrd.img
# sed -ri -e '/$/ rootovl/' /boot/cmdline.txt" rootovl" in cmdline
# echo "initramfs initrd.img" >> /boot/config.txt
Here's how it ended up in python:
def setup_readonly_root(self):
"""
Setup a readonly root with a tempfs overlay
"""
# Set up a readonly root using dracut's 'rootovl' feature.
# Eventually do this with systemd's systemd.volatile=overlay option.
# See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=945596
self.apt_install("dracut")
self.write_file("/etc/dracut.conf.d/overlay.conf", "filesystems+=overlay\n")
self.run(["dracut", "--force", "/boot/initrd.img", "4.19.75-v7l+"])
with self.edit_kernel_commandline("/boot/cmdline.txt") as parts:
# Add 'rootovl' to /etc/cmdline
if "rootovl" not in parts:
parts.append("rootovl")
# Add initramfs initrd.img to config.txt
with self.edit_text_file("/boot/config.txt") as lines:
if "initramfs initrd.img" not in lines:
lines.append("initramfs initrd.img")
Packages worth removing
- rsyslog is not needed in this setup. It can just be removed, as journald works well with volatile systems
- dphys-swapfile should be removed, in case it gets activated and tries to expand the ram by creating a swapfile in ram
- fake-hwclock is not needed since we disabled filesystem checks
Other links
Here is a series of link to other resources for doing something similar:
- https://medium.com/@andreas.schallwig/how-to-make-your-raspberry-pi-file-system-read-only-raspbian-stretch-80c0f7be7353
- http://hallard.me/raspberry-pi-read-only/
- https://wiki.debian.org/ReadonlyRoot
- https://learn.adafruit.com/read-only-raspberry-pi/overview
- https://wiki.archlinux.org/index.php/Overlay_filesystem
- https://www.domoticz.com/wiki/Setting_up_overlayFS_on_Raspberry_Pi