User avatar
TimG
Posts: 285
Joined: Tue Apr 03, 2012 12:15 am
Location: Switzerland

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 3:17 pm

ejolson wrote:A read-only root filesystem can prevent sdcard corruption when the Raspberry Pi suddenly loses power.
I've been wanting to try this for a while. A few days ago I got round to it, and it's been working very nicely.

Disc corruption with read-write Raspbian is sufficiently rare that I can't say definitively whether the read-only root is helpful. But it's worth a try in projects which encounter frequent power interruptions, and Ejolson's recipe made it easy to set-up.

So, many thanks to Ejolson!

PS. I modified the recipe slightly to account for 1st generation Pis and to make switching between read-only and read-write easier:

Code: Select all

if [ "$(uname -m)" = "armv7l" ]; then v=7; else v=; fi

cp /boot/config.txt{,.rw}
echo -e "\nkernel=kernel$v.img\ninitramfs initrd$v.img" | cat /boot/config.txt - > /boot/config.txt.ro
cp /boot/config.txt{.ro,}

cp /boot/cmdline.txt{,.rw}
echo -n "boot=overlay " | cat - /boot/cmdline.txt > /boot/cmdline.txt.ro
cp /boot/cmdline.txt{.ro,}

update-initramfs -c -k $(uname -r)
mv /boot/initrd.img-$(uname -r) /boot/initrd$v.img

drmacro
Posts: 37
Joined: Tue Mar 08, 2016 4:26 pm

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 3:49 pm

I mentioned in another post, just so it's here:
drmacro wrote:
Well that looks great, especially since is is with jessie...but

in the second set of instructions "cp -rp local-bottom overlay-bottom", get a "no such file or directory" error.

Sorry, about that. Please try just skipping that step. Unless an important package is missing it should still work. Let me know if you have any further trouble, because read-only with overlayfs should be quite easy.

drmacro
Posts: 37
Joined: Tue Mar 08, 2016 4:26 pm

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 3:56 pm

So I proceeded.

When editing local_mount_root(), I can see the part that is to be commented out. But the rest of the listing shown in this post is significantly different that the content of my overlay file. Are the differences to be added to my local_mount_root()? I'm guessing yes...but, I'd rather be sure.

Code: Select all

    # Mount root
    mkdir /upper /lower                <--------- is not in my local file
    if [ "${FSTYPE}" != "unknown" ]; then
        mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} /lower
    else
        mount ${roflag} ${ROOTFLAGS} ${ROOT} /lower
    fi
    modprobe overlay                                                                    <--------- is not in my local file
    mount -t tmpfs tmpfs /upper                                                    <--------- is not in my local file
    mkdir /upper/data /upper/work                                                <--------- is not in my local file
    mount -t overlay \                                                                      <--------- is not in my local file
        -olowerdir=/lower,upperdir=/upper/data,workdir=/upper/work \ <--------- is not in my local file
        overlay ${rootmnt}                                                                 <--------- is not in my local file
Last edited by drmacro on Fri Dec 09, 2016 6:48 pm, edited 1 time in total.

drmacro
Posts: 37
Joined: Tue Mar 08, 2016 4:26 pm

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 5:23 pm

Ok, so I read those lines a few more times and decided that it was meant that they should be added, I did so.

After boot. dmesg shows: overlayfs: failed to resolve '/upper/data': -2

'mount' shows nothing read only.

:?

drmacro
Posts: 37
Joined: Tue Mar 08, 2016 4:26 pm

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 6:03 pm

Went back and retraced my steps found a couple of things I missed in overlay. Fixed that and re-ran update-initramfs.

Now I see no errors, but mount still shows everything as rw. And, if I create something, say in /home/pi, it's there after re-boot.

:(
drmacro wrote:Ok, so I read those lines a few more times and decided that it was meant that they should be added, I did so.

After boot. dmesg shows: overlayfs: failed to resolve '/upper/data': -2

'mount' shows nothing read only.

:?

drmacro
Posts: 37
Joined: Tue Mar 08, 2016 4:26 pm

Re: Raspbian with Read-only Root

Fri Dec 09, 2016 7:58 pm

OK, after some experimentation it does appear root is read only now.

But, other than df showing filesystem for / being overlay, how would I know? (I know I can create something and re-boot to see if its still there...)

(PS: my apologies for all the chatter. :oops: )

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Sat Dec 10, 2016 1:52 am

drmacro wrote:OK, after some experimentation it does appear root is read only now.

But, other than df showing filesystem for / being overlay, how would I know? (I know I can create something and re-boot to see if its still there...)

(PS: my apologies for all the chatter. :oops: )
Root being mounted on overlay is the giveaway. The fact that it is otherwise difficult to tell is exactly what solves the compatibility problems and why all the software continues to work without any additional fiddling. Glad everything worked out.

pumpkinpi
Posts: 141
Joined: Fri Apr 18, 2014 7:11 pm

Re: Raspbian with Read-only Root

Mon Dec 12, 2016 5:20 am

Just tried this on a car based media server I built for the kids. Works! I didn't want to have any risk of corruptions on this thing. Nice little tutorial.

Thanks!

PPi

carljohanjensen
Posts: 3
Joined: Fri Aug 05, 2016 12:51 pm

Re: Raspbian with Read-only Root

Wed Dec 21, 2016 5:14 pm

This instruction is doing exactly what I like. :-) Thanks.
One thing: i did not find the local-bottom file ?
And one question: is there a simple way to "write through" the ram layer. ? Just in case I'd like to make some changes to the protected boot disk.

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Wed Dec 21, 2016 7:08 pm

carljohanjensen wrote:This instruction is doing exactly what I like. :-) Thanks.
One thing: i did not find the local-bottom file ?
And one question: is there a simple way to "write through" the ram layer. ? Just in case I'd like to make some changes to the protected boot disk.
The local-bottom stuff is not necessary, especially if it doesn't exist. For write access to the root filesystem simply revert the changes to /boot/config.txt and /boot/cmdline.txt and then reboot.

art_gl
Posts: 1
Joined: Wed Jan 04, 2017 10:46 pm

Re: Raspbian with Read-only Root

Wed Jan 04, 2017 10:56 pm

Thanks for the topic, this is exactly what I was looking for!

It is enough to remove boot=overlay from /boot/cmdline.txt to make system writable again.
FYI: this one-liner pretty-prints read/write statistics for memory card since the system was booted up:

Code: Select all

cat /sys/block/mmcblk0/stat | awk '{printf "Uptime read: %.3fMiB (%.1f%% I/Os merged) written: %.3f MiB (%.1f%% I/Os merged)\n", $3*512/1048576, $2/$1*100, $7*512/1048576, $6/$5*100}'

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Mon Jan 30, 2017 2:36 pm

how hard would it be to write a bash or python script that makes the necessary changes to all the files? would this be worth trying or do you think that there are many issues that could arise?

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Mon Jan 30, 2017 4:23 pm

spock wrote:how hard would it be to write a bash or python script that makes the necessary changes to all the files? would this be worth trying or do you think that there are many issues that could arise?
I suspect it would be pretty easy to automate. The difficulty of automating simple tasks with scripts is that the system as a whole becomes more complicated and difficult for the average person (who didn't write the script) to understand.

The Debian Live project consists of a set of scripts to build read-only root filesystems for live DVDs. In my opinion, after having used them, these scripts are too complicated to be helpful. For example, those scripts insist on building an entirely new OS image in a chroot environment, which can take an hour or more. Although Raspbian is also a Debian system, my post shows that accomplishing the same thing for the Pi can be done in a few minutes entirely by hand.

If you would like to create a Python script to automate the steps described in my original post, then by all means do so. It would be great if you included comments in the script explaining why each step is done and how things are supposed to work. It might be reasonable to cite this thread for further reference. A separate document describing how to use the script and the theory behind its operation would also be nice.

Thanks for the comments. If you write a script, I would be happy if you posted it here or a link to it.

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Tue Jan 31, 2017 1:32 pm

i am going to give it a try but don't know yet when i will find the time. :)
i will try to keep the script as simple as possible.

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Thu Feb 02, 2017 5:52 pm

here is the first version of my script. it seems to work but didn't have time to test it thorougly yet.

use at your own risk! :)

i would be happy about any suggestions for improvements. would there be a better way to patch the files? it's the first time i tried to do something like that. the script also needs more error checking at some places...

Code: Select all

    #!/usr/bin/env python3
    """ror.py - Read-Only Root

    This script automates the steps described by ejolson in this thread:
    https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=161416

    Usage:
        sudo ./ror.py create
            Initializes and enables read-only root file system.
        sudo ./ror.py disable
            Disables read-only root file system.
        sudo ./ror.py enable
            Enables read-only root file system.
        sudo ./ror.py destroy
            Cleans up all changes made by the script (read-only root must be disabled!).
    """



    import sys
    import os
    import shutil
    import subprocess



    def edit(filename, old, new):
        with open(filename, "r") as f: data = f.read()
        for i in zip(old, new):
            data = data.replace(i[0], i[1])
        with open(filename, "w") as f: f.write(data)
    def append(filename, s):
        with open(filename, "a") as f: f.write(s)
    def prepend(filename, s):
        with open(filename, "r") as f: data = f.read()
        with open(filename, "w") as f: f.write(s + data)



    def create():
       
        print("setting up read only root...")
       
        shutil.copyfile("/usr/share/initramfs-tools/hook-functions", "/usr/share/initramfs-tools/hook-functions._ror_backup_")
        shutil.copyfile("/boot/config.txt", "/boot/config.txt._ror_backup_")
        shutil.copyfile("/boot/cmdline.txt", "/boot/cmdline.txt._ror_backup_")
        print("backup created!")
       
        old = ['modules="$modules ehci-pci ehci-orion ehci-hcd ohci-hcd ohci-pci uhci-hcd usbhid"']
        new = ['modules="$modules ehci-pci ehci-orion ehci-hcd ohci-hcd ohci-pci uhci-hcd usbhid overlay"']
        edit("/usr/share/initramfs-tools/hook-functions", old, new)
        print("hook-functions edited!")
       
        shutil.copyfile("/usr/share/initramfs-tools/scripts/local", "/usr/share/initramfs-tools/scripts/overlay")
        shutil.copytree("/usr/share/initramfs-tools/scripts/local-premount", "/usr/share/initramfs-tools/scripts/overlay-premount")
        shutil.copytree("/usr/share/initramfs-tools/scripts/local-bottom", "/usr/share/initramfs-tools/scripts/overlay-bottom")
        print("overlay created!")
       
        old = [
            'ROOT=$(resolve_device "$ROOT")\n\n\tif [ "${readonly}" = "y" ]; then\n\t\troflag=-r\n\telse\n\t\troflag=-w\n\tfi',
            '# Mount root\n\tif [ "${FSTYPE}" != "unknown" ]; then\n\t\tmount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}\n\telse\n\t\tmount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}\n\tfi'
            ]
        new = [
            'ROOT=$(resolve_device "$ROOT")\n\n\t#if [ "${readonly}" = "y" ]; then\n\t\troflag=-r\n\t#else\n\t#\troflag=-w\n\t#fi',
            '# Mount root\n\tmkdir /upper /lower\n\tif [ "${FSTYPE}" != "unknown" ]; then\n\t\tmount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} /lower\n\telse\n\t\tmount ${roflag} ${ROOTFLAGS} ${ROOT} /lower\n\tfi\n\tmodprobe overlay\n\tmount -t tmpfs tmpfs /upper\n\tmkdir /upper/data /upper/work\n\tmount -t overlay -olowerdir=/lower,upperdir=/upper/data,workdir=/upper/work overlay ${rootmnt}'
            ]
        edit("/usr/share/initramfs-tools/scripts/overlay", old, new)
        print("overlay edited!")
       
        # todo: support BCM27835!
       
        release = os.uname().release
        subprocess.call(["update-initramfs", "-c", "-k", release])
        shutil.move("/boot/initrd.img-" + release, "/boot/initrd7.img")
        print("initramfs created!")
       
        append("/boot/config.txt", "\n\n\nkernel=kernel7.img\ninitramfs initrd7.img\n")
        print("config.txt edited!")
       
        prepend("/boot/cmdline.txt", "boot=overlay ")
        print("cmdline.txt edited!")
       
        print("done! please reboot!")



    def disable():
        shutil.move("/boot/config.txt._ror_backup_", "/boot/config.txt")
        shutil.move("/boot/cmdline.txt._ror_backup_", "/boot/cmdline.txt")
        print("root will be writeable after the next reboot!")



    def enable():
        if os.path.exists("/boot/config.txt._ror_backup_") and os.path.exists("/boot/cmdline.txt._ror_backup_"):
            print("already enabled!")
            return
        shutil.copyfile("/boot/config.txt", "/boot/config.txt._ror_backup_")
        shutil.copyfile("/boot/cmdline.txt", "/boot/cmdline.txt._ror_backup_")
        append("/boot/config.txt", "\n\n\nkernel=kernel7.img\ninitramfs initrd7.img\n")
        prepend("/boot/cmdline.txt", "boot=overlay ")
        print("root will be read-only after the next reboot!")



    def destroy():
       
        print("cleaning up...")
       
        shutil.move("/usr/share/initramfs-tools/hook-functions._ror_backup_", "/usr/share/initramfs-tools/hook-functions")
       
        os.remove("/usr/share/initramfs-tools/scripts/overlay")
        shutil.rmtree("/usr/share/initramfs-tools/scripts/overlay-premount")
        shutil.rmtree("/usr/share/initramfs-tools/scripts/overlay-bottom")
       
        os.remove("/boot/initrd7.img")

        print("done!")



    if __name__ == "__main__":
       
        if sys.argv[1] == "enable": enable()
        elif sys.argv[1] == "disable": disable()
        elif sys.argv[1] == "destroy": destroy()
        elif sys.argv[1] == "create": create()
Last edited by spock on Thu Feb 02, 2017 7:13 pm, edited 2 times in total.

epoch1970
Posts: 3364
Joined: Thu May 05, 2016 9:33 am
Location: Paris, France

Re: Raspbian with Read-only Root

Thu Feb 02, 2017 6:16 pm

Just in case.
I've spotted a recent post that solves the same problem via an init script. viewtopic.php?f=66&t=173063
Haven't tried it.
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Thu Feb 02, 2017 6:22 pm

spock wrote:here is the first version of my script.
I like it. Thanks for spending the time working on this.

The comments, usage and code seem straightforward. It would nice to include a "help" feature that would explain the usage if an unrecognized command is entered. You might want to check /etc/apt/sources.list to make sure the device is running the correct version of Raspbian before patching. I like how you coded your own patching algorithm. The standard Unix commands diff and patch do something similar.

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Thu Feb 02, 2017 7:11 pm

@epoch1970:
interesting! thanks for posting the link. has anyone tried it?

@ejolson:
thanks for your feedback! :) next time i find some time working on it i will go through your suggestions.

what do you think about the other script epoch1970 posted?

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Fri Feb 03, 2017 2:16 am

spock wrote:what do you think about the other script epoch1970 posted?
That script seems based on the same idea: pivot root to an overlayfs. The advantage of the script is simplicity by avoiding the initramfs, and I prefer simplicity. The disadvantage would be not having the educational opportunity to learn how an initramfs works. I suspect either way will protect the sdcard equally well.

Most x86 distributions use an initramfs, so that is why I did things the way I did. In particular, my instructions can readily be modified to work for standard Ubuntu, Mint and Debian. Note that historically, x86 systems used an initramfs because there were so many different kinds of disk drivers that it was impractical to include all of them built into the kernel. As there are fewer kinds of Pi computers, an initramfs is generally not used in Raspbian.

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Fri Feb 03, 2017 10:55 am

i roughly understand how this overlayfs idea works but how could i best learn about the details? what is this upper and lower thing for example? :)

how did you learn about all of this? is this your job?

ejolson
Posts: 3260
Joined: Tue Mar 18, 2014 11:47 am

Re: Raspbian with Read-only Root

Sat Feb 04, 2017 5:40 pm

spock wrote:i roughly understand how this overlayfs idea works but how could i best learn about the details? what is this upper and lower thing for example?
The Linux kernel contains documentation on unionfs. I also ran across some bug discussions in online forums.
spock wrote:how did you learn about all of this? is this your job?
I teach mathematics and how to use computers to solve mathematics problems. I've been interested in computers since childhood. As a teacher, one of the primary things I find important is learning. As a result I've accumulated a bit of computer knowledge over the years.

This appears to be post 1000 for me on the forum. As that was my limit, I will now take a break from the forum for some time. I still owe someone a reply about Bluetooth, so 1000 may turn out to be a soft limit. In closing I would like to thank all the people here for interesting discussion and even making me laugh a few times. All the best.

vandiwa
Posts: 1
Joined: Thu Mar 16, 2017 7:29 pm

Re: Raspbian with Read-only Root

Thu Mar 16, 2017 7:40 pm

This works great, and I love the simplicity of it compared to another approach I tried where root was mounted read-only. The problem I have is that I need to be able to occassionaly write to the actual root file system changing things like wpa_supplicant.conf. Is there a way to revert to the rw file system that doesn't involve a reboot? If not, I have some workarounds involving temp copying to /boot, changing cmdline.txt and rebooting, then realizing I'm in that situation, copy the files I need to root, change cmdline.txt back again and reboot, but that seems a little convoluted.

*Update - even though it's a little convoluted, I did get it to work by making use of a service that writes a flag file to /boot and then reboots with cmdline.txt modified. The next time it boots, is sees the flag, makes the changes in the rw file system, removes the flag file and reboots again, so there are two boots required to change the config, but it's working.

LGarber
Posts: 6
Joined: Sun Mar 26, 2017 9:39 pm

Re: Raspbian with Read-only Root

Sun Mar 26, 2017 9:44 pm

ejolson and spock rock! I just spent the last 5 hours playing around with psuter's solution viewtopic.php?f=66&t=173063 because it sounded so slick. But on my NOOBS RPi 3, I couldn't get it to work. Then I went back to spock's script and in 10 minutes I was up and running. Spent half of that time trying to confirm that it indeed worked. THANK YOU!!!
....Larry

spock
Posts: 205
Joined: Sun Oct 02, 2011 10:33 am

Re: Raspbian with Read-only Root

Mon Mar 27, 2017 5:33 pm

for me the script doesn't work anymore with the newest raspbian. the directory local-bottom doesn't exist anymore. does anyone know why?

User avatar
kusti8
Posts: 3439
Joined: Sat Dec 21, 2013 5:29 pm
Location: USA

Re: Raspbian with Read-only Root

Mon Mar 27, 2017 6:29 pm

spock wrote:for me the script doesn't work anymore with the newest raspbian. the directory local-bottom doesn't exist anymore. does anyone know why?
Didn't exist for me also, but it still worked.
There are 10 types of people: those who understand binary and those who don't.

Return to “General discussion”