Read only rootfs

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:

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

Other links

Here is a series of link to other resources for doing something similar: