How to make Raspbian read-only

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

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.

I have been using this guide from the pi3g blog when creating my Ambilight project and it works pretty well! If you are using a Raspberry Pi for any kind of project and want to be able to turn it on and off quickly without damaging the SD card, this it the guide is for you.

Backup your SD card

Before attempting this tutorial, I recommend that you make a backup of your SD card using Win32 Disk Imager or a similar tool. Just download and run the tool, specify a location and click read to make a backup to disk.

How to make Raspbian read-only

First of all we want to disable swapping by running the following commands:

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

Next we’re going to install UnionFS which 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. If you run into issues installing the package (404 Not Found) you should take a look at this blog post for a temporarily workaround.

apt-get install unionfs-fuse

Create the script used for mounting UnionFS:

nano /usr/local/bin/mount_unionfs

and add the following content to the file:

#!/bin/sh

[ -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}
else
/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}
fi

Once you’ve saved the file you’ll need to make it executable:

chmod +x /usr/local/bin/mount_unionfs

Next we have to update fstab using nano /etc/fstab and make sure it looks like this:

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

Now it’s a good time to create the required directories:

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

Before rebooting the system we’ll create one last file. This script will be used to make the system temporarily writable again in case you need to make any changes to it:

nano /home/pi/remount.sh

and add the following content to the file:

#!/bin/bash

# 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
done

sleep 1

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

Once you’ve saved the file you’ll need to make it executable:

chmod +x /home/pi/remount.sh

Finally reboot and the system should be read-only:

sudo reboot -d -f -i

 

How to remount the system as writable

If you need to install packages or make other changes to the image you can easily make it writable again using:

./home/pi/remount.sh

When all changes are made simply reboot the system and the system should be read-only again.

 

Share this:

4 comments, add yours.

Avatar

belese

Thanks for this guide,
i’ve to changed “UsePrivilegeSeparation no”
in file
/etc/ssh/sshd_config

to have ssh working.
don’t know why, just have info from here
http://petr.io/en/blog/2015/11/09/read-only-raspberry-pi-with-jessie/

Avatar

Damian

Great work! Thank You!

Avatar

Damian

How I Can install pacages in rw mode?
rw mode is in chroot, i got errors. How I can enable rw mode for installing packages?
Thank You!

Avatar

adlp

‘lo…
I’m not a master in awk parsing, but I’ve replace
ROOT_MOUNT=$(grep -v “^#” /etc/fstab | awk ‘$2==”/” {print substr($4,1,2)}’)
by
ROOT_MOUNT=$(echo $3 | cut -d’,’ -f1)
Why :
* the result was not like I want
* I do not understand why the grep was used when we get everything needed in parameters
* I do not understand awk (oops :])
Please correct me 🙁

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.