Apr 032014

What is this about?

How to set up a Raspbian system as a read-only system in a couple of easy steps.


This penguin has been doing a lot of reading as of lately.

Why is this of interest to me?

The filesystem on the Raspberry Pi’s SD card, as every filesystem on every computer, can be corrupted if you disconnect the power suply.

Once you make the filesystem read-only (all changes go to a RAM-Disk), you will be able to disconnect the power supply whenever you want.

An additional bonus is less wear on the SD card – sometimes you do NOT want the logfiles which a standard Linux / Raspbian will write to anyway. Our solution will write those to a RAM-Disk and discard them on reboot / power cycling.

Last but not least, you can set up a known state to boot into, experiment, and if things go wrong, simply reboot.

How-To make Raspbian read-only

all commands to be run as root (sudo su) if not specified otherwise.

This how-to is based on another how-to I found on the Internet, in German. Thanks guys!

Disable swap

dphys-swapfile swapoff
dphys-swapfile uninstall
update-rc.d dphys-swapfile disable

Install UnionFS

UnionFS is an overlaying filesystem (you can mount from several different locations into the same folder). In case of collisions, UnionFS uses priorities for the filesystems. It is frequently used to create RAM-Disk Overlays for read-only systems, for instance also with Live CDs.

aptitude install unionfs-fuse

Create mount script

nano /usr/local/bin/mount_unionfs

Add the following content to this file:

 ROOT_MOUNT=$(awk '$2=="/" {print substr($4,1,2)}' < /etc/fstab)
 if [ $ROOT_MOUNT = "rw" ]
   /bin/mount --bind ${DIR}_org ${DIR}
   /bin/mount -t tmpfs ramdisk ${DIR}_rw
   /usr/bin/unionfs-fuse -o cow,allow_other,suid,dev,nonempty ${DIR}_rw=RW:${DIR}_org=RO ${DIR}

make it executable:

 chmod +x /usr/local/bin/mount_unionfs

Update /etc/fstab:

nano /etc/fstab

Modify the file to read (adjust partitions for NOOBS!) as follows:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    ro                0       2
/dev/mmcblk0p2  /               ext4    ro,noatime        0       1
mount_unionfs   /etc            fuse    defaults          0       0
mount_unionfs   /var            fuse    defaults          0       0
none            /tmp            tmpfs   defaults          0       0

Prepare the directories

cp -al /etc /etc_org
mv /var /var_org
mkdir /etc_rw
mkdir /var /var_rw

At this point your Raspberry Pi should be read-only already. You can verify this with


This command should show something like the following:

/dev/root on / type ext4 (ro,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=215824k,nr_inodes=53956,mode=755)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=44820k,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=89620k)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
/dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
ramdisk on /etc_rw type tmpfs (rw,relatime)
unionfs-fuse on /etc type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
ramdisk on /var_rw type tmpfs (rw,relatime)
unionfs-fuse on /var type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
none on /tmp type tmpfs (rw,relatime)

This indicates to you that the filesystems are mounted read-only and unionfs is active.

Clean up the Log directory

mount -o remount,rw /
for f in $(find . -name \*log); do > $f; done
cd /var_org/log
rm -f *.gz


Another reboot and you’re done!


How-To Install additional Packages after “read-only-modding”

You’ve got to remount the root filesystem as readable. For instance, as root, you can do:

mount -o remount,rw /
aptitude update
aptitude install stress
  • Rich

    Thanks! Great info. Is there a way to mount users home directories in a ramdisk? So at least some files can be temporarily writen?

    • admin

      Sure, there is a way to mount a RAM Disk over a user directory. I think it should work like this:

      Mount your system read-write

      cp -al /home/pi /home/pi_org
      mkdir /home/pi_rw

      and add a new line to /etc/fstab

      mount_unionfs /home/pi fuse defaults 0 0

      Reboot. Now /home/pi should have a RAM Disk mounted over it.

  • Rich

    Also I can’t add new devices after doing this.

    • admin

      Remount in read-write mode, add your devices, reboot.

  • BaM

    Here’s a slightly improved version of “mount_unionfs”, it is aware of comments (“#”), fails on missing parameter and looks for != “ro” instead of == “rw”, in case the root fs is configured with option “defaults,…” instead of “rw,…”:

    [ -z “$1” ] && exit 1 || DIR=$1
    ROOT_MOUNT=$(grep -v “^#” /etc/fstab | awk ‘$2==”/” {print substr($4,1,2)}’)
    if [ “$ROOT_MOUNT” != “ro” ]; then
    /bin/mount –bind ${DIR}_org ${DIR}
    /bin/mount -t tmpfs ramdisk ${DIR}_rw
    /usr/bin/unionfs-fuse -o cow,allow_other,suid,dev,nonempty ${DIR}_rw=RW:${DIR}_org=RO ${DIR}

  • k3a

    Thanks for the nice guide. Remount / is not enough for updating/deleting packages. I have made quite a neat script for remounting + binding original directories into a chroot.


    # remount root rw
    mount -o remount,rw /

    # prapare target paths
    mkdir -p /chroot
    mkdir -p /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}

    # mount special filesystems
    mount -t proc proc /chroot/proc
    mount –rbind /sys /chroot/sys
    mount –rbind /dev /chroot/dev

    # bind rw directories
    for f in {etc,var}; do mount –rbind /${f}_org /chroot/$f; done

    # bind remaining directories
    for f in {bin,boot,home,lib,opt,root,run,sbin,tmp,usr}; do mount –rbind /$f /chroot/$f; done

    # chroot
    echo “Note: /boot is still mounted read-only, remount to read-write if needed.”
    echo -e “e[33mYou are now in read-write chroot. Use CTRL+D when done to exit chroot and mount read-only again.e[39m”
    chroot /chroot /usr/bin/env PS1=”(rw) u@h:w$ ” /bin/bash –noprofile -l

    # unmount mounts
    for f in /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}; do
    umount -l $f

    sleep 1

    # remount read-only again
    echo -e “e[32mChroot left, re-mounting read-only again.e[39m”
    mount -o remount,ro /

    • Paulo Fernando Ornellas


      • k3a

        Because if you just remount, /etc_org and /var_org will be read-write, but your /etc and /var are still unionfs and package manager works with these directories. So with just remounting, your changes won’t persist after reboot. My script prepares chroot with binded /etc_org => /etc and other dirs inside that chroot.

        • Paulo Fernando Ornellas


    • Captain Murloc

      I know this comment is quite old, but I’m new on Linux/RasPi and I don’t know how to use this script.
      Do I need to create a file containing this code in the aim to call it when I need to edit some files on /etc for example ?


      — Captain Murloc

      • k3a

        For this read-write remount script (to be able to use apt-get to update software), just place the code including #!/bin/bash as the first line in a text file. Save the text file, I named it rwchroot.sh and make it executable by: chmod a+x rwchroot.sh Then you can run it ./rwchroot.sh Hope it helped.

        • Captain Murloc

          Hey k3a ! Thanks for your answer. This is what I did and it works well ! :)
          Thank you.

          See you guy !

          — Captain Murloc

          • k3a

            I have been using RPi on 5 cameras for almost half a year, so you may like my other comments here. Additional few notes – filesystem on one RPi got corrupted despite being mounted readonly with unionfs. I guess just a cheap SD card. In the end I made it true read-only without unionfs as it wasn’t so much more work (according to http://blog.gegg.us/2014/03/a-raspbian-read-only-root-fs-howto/). It was worth it, I kept some parts of /var readonly (apt stuff) and put several symlinks to /tmp for various subdirectories of /var. That guy also suggests modifying some rc scripts but it doesn’t seem to be necessary and it’s dangerous – if you update the system, those scripts may revert to original state. I found out adding ‘fastboot noswap’ at the end of the bootline /boot/cmdline.txt disables both filesystem check and swap. I got a serious problem with cron though! Because of readonly filesystem, fake-hwclock is not used so clock can’t store last date/time on reboot. I had ntpdate clock update over NTP but for some reason it once probably took long to update and it resulted in many reboots (as I have reboot scheduled every day) – be careful of this if using cron. I solved it by implementing my own ‘cron-like’ script which is just a bash script with while and various sleeps and ifdefs. If someone wants to use it too, here it is (to be placed as /usr/local/fakecron.sh) https://paste.k3a.me/view/4515b0a4 . I use this rcscript for it (to be placed to /etc/fakecron) https://paste.k3a.me/view/0a995efd . Both needs to be executable chmod a+x and to make this fakecron to start at boot, do ‘insserv fakecron’. I am considering writing a completely new article about all my changes to my blog. That would be nicer I guess. I will do it when I have time and let all people from comments here to know about it. Bye for now :)

          • Captain Murloc

            Hey !
            All the things you talk about interests me. I will probbaly need your help soon. But for now, I just want to thank you. Because you really help me.

            For my use, I will try to work with unionfs. I will see. 😉
            But I note your links.

            Bye ! :)

            — Captain Murloc

          • k3a

            oh and the reason for using read-only without unionfs for me was, that once when RAM memory got exhausted, kernel killed unionfs user-space process, creating filesystem state inconsistent. Manual reboot was required. Yes, memory should never be exhausted completely but sometimes you make a mistake (e.g. by writing logs to tmpfs) and then this may happen… So having user-space filesystem like unionfs is not very ‘reliable’ solution and for an embedded system like RPi, it requires only a little bit more work to get it truly readonly without unionfs.

          • k3a

            I wrote about my experience with read-only RPi, without unionfs to my blog. Please ignore English mistakes, I wrote it just now in a hurry so it can help you right away. :) Will update it later… http://k3a.me/how-to-make-raspberrypi-truly-read-only-reliable-and-trouble-free/

  • farhan rasheed

    I cannot add any printers in cups even after mount -o remount,rw /
    Any help appreciated!

  • Anon Wibble

    I tried BaM’s advice but there was some pasting formatting error, and so when i rebooted it killed my rpi installation ! So be careful.

  • Anon Wibble

    You can do the same also with the /home/ directory because, unless you do, you wont be able to do things like start up xorg etc. This webpage has been very useful. Also i have a script to turn on and off the read only filesystems so that you can install packages.


    function ErrorMessage(){
    echo “Usage: ${0} enable|disable|temp”

    function SanityCheck(){
    cat /etc/fstab

    if [ $# -ne 1 ]
    if [ “${1}” == “enable” ]
    echo “Enabling read only filesystem!”;
    mount -o remount,rw /
    cp /etc/fstab-RO /etc/fstab
    cp /etc/fstab-RO /etc_org/fstab
    elif [ “${1}” == “disable” ]
    echo “Disabling read only filesystem!”;
    mount -o remount,rw /
    cp /etc/fstab-RW /etc/fstab
    cp /etc/fstab-RW /etc_org/fstab
    elif [ “${1}” == “temp” ]
    echo “Remounting RW temporarily!”;
    mount -o remount,rw /

    A reboot is required to make the changes in this script effective.

  • Matthew

    I follow your tutorial.

    However /etc directory is still writable (there is no mount_unionfs
    if I execute mount command) and there is no .unionfs dir in /etc

    /home and /var directory are working just fine

    However when I manually call “mount_unionfs /etc” it is actually
    working. It seems that /etc directory doesn’t working only on boot.

    Any idea? If you need any log or dump of files let me know – I’ll paste them.

    • have you had a look at the improved script in the comments? Maybe it can solve the problem.
      The script in this blogpost works for us (on rebooting the Pi) and will prevent direct edits to /etc.

      • Matthew

        Unfortunatelly there is still some thing wrong. :/ I spent a lot of hours but still no solved the problem.

        I’ve tried a lot of times and whenever I prepare my SD card and make it R/O everything works fine, but I can’t do any changes in for example init.d

        – I’ve prepared my card
        – I’ve made R/O mode
        – I can’t maniuplate in init.d, so I can’t remove some init scripts.

        I’ve setup a asplashscreen (before R/O). After R/O I can’t remove it (of cource I’m doing it in R/W mode). I’ve even delete whole asplashscreen script (this script doesn’t exists any more in /etc/init.d) but still after reboot splash is showing.

        Does linux have some cache mechanism?

        Another two examples:
        – I can’t change hostname after R/O mode. Hostname in files is changed (I did it in R/W mode) but after reboot it stil setting the old hostname despite the fact that new hostname exists in files. However when I manually run /etc/init.d/hostname, hostname is changing. But after reboot the old hostname is still showing.

        – I deleted whole /etc/fstab, but after reboot it’s still working and my partitions are in R/O mode (on what basis since there is no fstab file on whole SD card). I have some errors on start, but raspian still mounting partitions like they were in fstab.

        It’s all seems that linux somehow remebered everthing that was before R/O in initialization scripts (init.d, fstab, hostname etc.) and I can’t make any changes.

        Thanks for any help.

        • Matthew

          Ok, I managed something.

          I’ve mounted rpi SD card on my debian and look at the directories. In /etc directory there where still old name in hostname.

          What I’m thinking about:

          1) RPi is running
          2) RPi is mounting sd card and directories from fstab
          3) Hostname script is running with old /etc/hostname
          4) In mount_unionfs script the last line is “binding” the /etc folder with /etc_org (so in fact when I cat /etc/hostname I’m seeing new hostname)
          5) System is loaded, hostname.sh was fired before binding /etc

          The same way I can’t remove asplashscreen from update-rc.d because this script run before fstab bind /etc

          I think that the /etc folder is very sensitive sa mount_unionfs script has a bug (in my case). This line:

          ROOT_MOUNT=$(awk ‘$2==”/” {print substr($4,1,2)}’ < /etc/fstab)

          should awk fstab from /etc_org, not from /etc, because I can't really modify the original /etc/fstab file.

          But, is there any way to get into original /etc folder? Most of time when I do umount /etc the directory is busy (but sometime it is not), so I can't modify files in there (except I mount sd card with debian on my PC). If there was any way to get into original /etc folder while RPi is running I'll be very happy. :)

  • legramo

    Thanks for this awesome guide, SD corruption is the biggest problem i’ve found. I’ve followed your instructions carefully and everything works fine, but i should solve the next problem… i can’t execute a python code allocated at my home directory (obviously is a Read-only file system). I’d very grateful if anyone could suggest how to solve it!

    • Is the executable bit set?
      Try to copy the python file to the /tmp directory (RAM disk), and run it.

      Try to run it using python (python /tmp/file.py)

      “Can’t execute” can mean many things.

      • legramo

        Thanks for your response. Finally i decided to move the python file to /etc_rw and run it in that directory (RAM disk and writable). The problem was solved.

        Anyway i’ve found a new problem, when i modify a file located at the directory /etc (for instance /etc/wpa_supplicant/wpa_supplicant.conf or /etc/udev/rules.d/70-persistent-net.rules), first i run “sudo mount -o remount,rw /” (in order to make the directory /etc writable) and apparently the changes have written properly. But unfortunately after rebooting the RPi the changes have dissapeared (i guess that the new changes weren’t written in the SD Card)!

        Do u have any suggestion? Thx in advance!

  • VooDoo

    Thanks for this useful guide. It’s good known that the filesystem corruption problems are quite common in the Rpi.

    Anyway, after testing your idea i’ve found an important issue… after remounting root rw using “sudo mount -o remount, rw /” (as you explain) important directories as /etc aren’t persistent anymore in the SD Card. I mean, you can modify them but after rebooting the Rpi the changes are lost.

    Any idea? Thanks.

    • k3a

      You are right. That’s why I made the rwchroot.sh script. Look at my other comment here.

      • SciLor

        How do I use this script?

        I get following output

        mount: mount point /chroot/etc does not exist
        mount: mount point /chroot/var does not exist
        mount: mount point /chroot/bin does not exist
        mount: mount point /chroot/boot does not exist
        mount: mount point /chroot/home does not exist
        mount: mount point /chroot/lib does not exist
        mount: mount point /chroot/opt does not exist
        mount: mount point /chroot/root does not exist
        mount: mount point /chroot/run does not exist
        mount: mount point /chroot/sbin does not exist
        mount: mount point /chroot/tmp does not exist
        mount: mount point /chroot/usr does not exist
        Note: /boot is still mounted read-only, remount to read-write if needed.
        You are now in read-write chroot. Use CTRL+D when done to exit chroot and mount read-only again.
        chroot: failed to run command `/usr/bin/env’: No such file or directory
        umount: /chroot/bin: not found
        umount: /chroot/boot: not found
        umount: /chroot/dev: not found
        umount: /chroot/etc: not found
        umount: /chroot/home: not found
        umount: /chroot/lib: not found
        umount: /chroot/opt: not found
        umount: /chroot/proc: not found
        umount: /chroot/root: not found
        umount: /chroot/run: not found
        umount: /chroot/sbin: not found
        umount: /chroot/sys: not found
        umount: /chroot/tmp: not found
        umount: /chroot/usr: not found
        umount: /chroot/var: not found
        Chroot left, re-mounting read-only again.

        • k3a

          This script was created for Raspian and for read-only changes made according to this article (using unionFS) and should work fine without any other changes. In your error log there is /usr/bin/env missing which suggests you have somehow modified OS installation. It looks like /chroot or /chroot/etc (and other) folders are not created but creations of them is part of the script. It possibly means that / is not remounted read-write but remount is the first command in the script. It’s difficult to help you this way as I don’t know more information about your installation. Also this is a bash script so please make sure you have #!/bin/bash as the first line.

        • mcgillow

          Check in the script if you didn’t miss a slash (/) in your second mkdir command.

      • legramo

        Your script works perfectly! Thanks for your useful help!

  • Rod

    Hi guys,
    Thanks for the guide

    what about this errors?
    Mounting local filesystems…fuse: missing mountpoint parameter
    /usr/local/bin/mount_unionfs: 9: /usr/local/bin/mount_unionfs: /etc: Permission denied

    Same thing for /var

    I,ve tried chmod 777 /etc but no change

    Many thanks

    • Rod

      It is done, just a written error

  • k3a

    After months of success with this read-only solution I am writing to report some more tips.

    1. For updating system using apt-get/aptitude, I suggest you the script I wrote bellow. It works well, though rarely it won’t remount back read-only and reports ‘file system busy’. Keep an eye on it. Sometimes repeating the ro remount again works, other time it’s better to safely reboot.

    2. Consider following some ideas in http://blog.gegg.us/2014/03/a-raspbian-read-only-root-fs-howto/ (obviously don’t do any read-only filesystem changes as you are using UnionFS for that). Especially these things are VERY important and why (in order of that article):

    a) you can get rid of wolfram-engine if you don’t use it – it’s quite big

    b) you can also get rid of other desktop/graphical things which are useless in your headless setup or just won’t work with read-only root, for example triggerhappy, X11, dbus, dphys-swapfile. Logrotate is useless as well as you are not storing any persistent logs.

    c) VERY IMPORTANT note about cron/anacron – it won’t work in standard installation because UnionFS does something like hard-link to /etc. So cron will refuse to use /etc/crontab. To fix that, I simply binary-edited cron binary and changed /etc/crontab to /usr/crontab. You may potentially find some nicer solution but this one works. I used vim -b for that task.

    d) set up busybox syslog instead of standard syslog. Standard syslog would write to /var and thus to your RAM and after a few weeks or months you may end up with out of memory. Because of that I made a tiny ruby script which sends me busybox syslog entries to a central server via TCP. Here is client written in C https://paste.k3a.me/view/9ba16c00 and here is the server written in Ruby https://paste.k3a.me/view/1bed6d86. Not ideal in case your box loses internet connection or you want to debug network-related problems – but for those cases you can connect to RPi via an UART console anyway and read syslog there.

    e) another VERY IMPORTANT changes are to those checkroot.sh and checkfs.sh as he mentions. If you don’t do that, your box will not start again in few weeks after a reboot. That is because filesystem check will refuse to continue when it finds that the last change is from the future. And it will be if your Raspberry doesn’t have an external clock storage. On shutdown/reboot, it stores the current time to /var but after reboot /var is reset to your read-only default state, thus old time. And because of this you also want to set up time synchronization (e.g. NTP). And remove fake-hwclock.

    f) you can keep alsa-utils if you use sound apps of course. Changes after “Change /etc/fstab as follows:” inclusive are not relevant as you use UnionFS.

    g) if you use wifi networking, you may need to update firmware http://raspberrypi.stackexchange.com/a/17179 and if you use camera at the same time, make sure to disable camera preview as it somehow leaks the memory and I suggest you to reboot the box from time to time (automatically using cron). I do it daily.

    This experience was gathered in weeks of fails when setting up read-only box which was installed on a remote location. You can imagine how annoying it was to see that the box is down again, travelling there and after a week due to these little things. But now it works perfectly – not a single issue in months!

  • JustAnEngin33r

    I followed the directions here and all seemed to go according to plan, with one [major] sticking point: My root filesystem is still mounted rw!! Everything in my “mount” output matches, except for the first line (/dev/root is mounted “rw,relatime” whereas my fstab has commanded “ro,noatime”… apparently to no avail :)

    I’ve double-checked my fstab and it’s identical to the one in the article above. Is there some other trick I need to do? A kernel or bootloader parameter, perhaps?

    Also, one correction: under “Clean up the log directory” it does not say what the working directory should be prior to running the find command. I went to / just in case, although I’m still not 100% clear what that was supposed to accomplish.

    • Cleaning up the logs will free some space on your SD card – they are unnecessary for the read-only image. Future logs will be written to the RAM-Disk and hence discarded on reboots.

      Did you create the /usr/local/bin/mount_unionfs script and make it executable?

      Also you should reboot once after everything is set up.

      • JustAnEngin33r

        Yes, I double-checked /usr/local/bin/mount_unionfs. By the way, I have never seen an fstab where the first field contains the name of an executable or script, rather than a device file or UUID as usual. I tried looking in the documentation and couldn’t find a reference there either. Is this an undocumented feature of the fstab file?

        In any case, I am fairly sure mount_unionfs ran, because all of the unionfs mounts are in place. The only thing wrong is that my root filesystem is still mounted rw. Here is the output of “mount”:

        /dev/root on / type ext4 (rw,relatime,data=ordered)
        devtmpfs on /dev type devtmpfs (rw,relatime,size=219764k,nr_inodes=54941,mode=755)
        tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=44788k,mode=755)
        tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
        proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
        sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
        tmpfs on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=89560k)
        devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
        /dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
        ramdisk on /etc.rw type tmpfs (rw,relatime)
        unionfs-fuse on /etc type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
        fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
        ramdisk on /var.rw type tmpfs (rw,relatime)
        unionfs-fuse on /var type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
        none on /tmp type tmpfs (rw,relatime)

        Anything else I can check?

        • Hi,

          I believe some visitors had some quite valuable suggestions in the other comments – I hope looking through them might take care of this issue?
          Unfortunately right now I am very busy with launching our new product ( https://anonymebox.com ), and can’t help you beyond this.


          • JustAnEngin33r

            Hi Max,
            Unfortunately, I’m pretty sure now that my issue is unrelated to any of the comments here :( But you are not obligated to help; you’ve already done us a great service by posting this article. So thank you! and good luck with the anonymebox.

          • droneshield

            Check your fstab to make sure mmcblk are ro – it is not sufficient to just paste the bottom lines (I learned the hard way). Check the entire fstab file.

  • Andrea Guglielmini

    Hi, how can i put the /home directory in ‘readonly’ editing the fstab?
    I tried to rename home to ‘home_org’ and add a line in fstab but it’s still in readonly..
    Can you help me?

    • Hi,

      Unfortunately right now I am very busy with launching our new product ( https://anonymebox.com ), and can’t help you beyond this:

      /home should generally also be readonly if / (the root file system) is readonly.


      • Andrea Guglielmini

        Hi Max, thankyou for the answers!
        I need /home rw because otherwise startx (x11?) won’t start!

        I’ll try to find a way!
        This tutorial is really useful

        • Sorry, I misunderstood you …
          I would try to follow the procedure for /etc, it should create a RAM Disk for /home as well.

          • Andrea Guglielmini

            I made a mess with /boot/cmdline.txt! Now it’s working even for /home 😉

          • Glad it worked out for you!

          • JustAnEngin33r

            Hi Andrea,
            Could you share your /boot/cmdline.txt? I trying to make this work but for some reason the kernel is ignoring my fstab and mounting root rw even when I ask for ro. It’s a long shot but I wonder if the problem could be related to my cmdline.txt.

          • Andrea Guglielmini

            Hi! It’s

            dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 ro rootfstype=ext4 elevator=deadline rootwait fbcon=map:1 fbcon=font:ProFont6x11

            The “ro” after mmcbl..p2 puts “/” in readonly.

            Then i moved the “pi” directory from /home/pi to /var/home/pi
            chmod -r 777 /var/home/pi
            Then i put a link from /home/pi –> /var/home/pi
            In this way the /home/ directory is readonly but you can use “startx” and it will execute normally because it has writing permission in /var/home/pi

          • Thank you for sharing that with all.

          • JustAnEngin33r

            Hi Andrea, that did the trick! My cmdline was pretty much the same, except it did not have the “ro” after the root=… After adding that, I am now booting up with read-only root.

            Max (and others), I wonder if your kernel command lines already had the “ro” option? Maybe this needs to be added to the tutorial.

            Anyhow, thanks everybody for your help.

  • Captain Murloc

    Hey Max,

    Thanks a lot for the guide. I know you are very busy but I have some questions.
    In fact, everything is OK for the read-only partition but I would like to boot on the graphical desktop (or directly on console). Now, I’m booting on an odd interface asking me to login (seems to be lightdm).
    Moreover, I cannot connect myself to the Pi through this interface. I use default login and password but nothing seems to work.
    The only thing that I can do is to press ALT+CTRL+F(1,2,3,4,…) to show the terminal (and to login from here). But I can’t access to the graphical desktop (or directly to the console).

    Do you know why ? And how I can solve my problem ?

    Thank you.

    — Captain Murloc

    • Please read through the other comments – X needs write rights on the home directory, I believe. Other people seem to have fixed it

  • Mouhamed Halloul

    sorry i am new to all this, i want to remout /etc/initab to rw , any way to do that ?
    Thank you

  • legramo

    Hey Max, thanks for the guide, it’s very useful!
    I’m wondering how to execute your script from another one and afterwards execute more commands within the new environment. The reason is the command ·”expect”, which let me control my Rpi from remote. Unfortunately, once i execute your script using “expect”, i’m unable to execute more commands from remote in the new environment (rw) root@raspberrypi:/home/pi$
    Any idea?
    Thank you

  • Craig

    Is there a way to modify the /boot/config.txt file after applying this read only procedure? I tried the “mount -o remout,rw /” but my changes to config.txt are undone for the next reboot. I need to add the “max_usb_current=1” line so that I can get the 1.2A for the four USB ports instead of 600mA.

  • Mehmet Can Akpinar

    Dude thanks a lot!

  • Y M

    i tried this and it works but what if i want the changes to persist ( users added and other files) do i have to move them myself or is it possible to sync ro with the tmp files ?

  • Olafs Bāliņš

    This guide works pretty good with latest Raspbian and Pi 3 B+. But there are one major problem – after “reboot” command it hangs. Only errors I see is “Failed unmounting /etc /etc_rw /var_rw”. Could that be reason for hanging at reboot and what could be solution for this?

    • Bo Herrmannsen

      i have the same problem, and this pi will be remote at some point so need to figure what is “wrong”

      • Bo Herrmannsen


        do you have any idea why its hanging at reboot?

        worked fine otherwise

Optimization WordPress Plugins & Solutions by W3 EDGE