Read Only Raspbian
Sometimes you need a raspberry pi to be hardened against unclean shutdowns, or pulling the SD card out, or you're just sick of the card getting corrupted. These are instructions for ruggedising your raspbian image so it's far lass likely to get messed up. Derived mostly from https://wiki.debian.org/ReadonlyRoot.
Install Raspbian to an SD card as per the instructions, either the regular or lite image, then boot and log into your pi.
These instructions were written for debian jessie.
Expand the Filesystem
We will create a new partition layout with the existing /boot, a slightly bigger / (root), and a new /var to hold any files that need to be writable.
sudo fdisk /dev/mmcblk0
type p and hit return, write down the Start of /dev/mmcblk0p2:
Command (m for help): p Disk /dev/mmcblk0: 7.5 GiB, 8068792320 bytes, 15759360 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x6f92008e Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 131071 122880 60M c W95 FAT32 (LBA) /dev/mmcblk0p2 131072 13019679 13150751 1.3G 83 Linux
Delete partition 2 (yea, really) by typing these letters (remember to press enter after each one).
Now make a new partition 2 in the same starting location but bigger, replace <these sections> with the correct number:
n p 2 <The exact number from Start before (131072 for me)> +<Half the size of your SD card (eg '4' for an 8GB card)>G
Now print the table again with p and write down the End of /dev/mmcblk0p2
Now make a new partition 3 in the rest of the space:
n p 3 <The End of partition 2, PLUS ONE> <just press return to let it use the rest of the SD card>
Now if that all went well type w and press enter to save the new partition table. Otherwise press q to forget everything you just did and try again.
Expand the root filesystem in partition 2
sudo partprobe sudo resize2fs /dev/mmcblk0p2
Make the new filesystem in partition 3
sudo mke2fs -t ext4 /dev/mmcblk0p3
Mount the new filesystem and move things into it
sudo mount /dev/mmcblk0p3 /mnt/
Copy the content of /var into it
sudo cp -rp /var/* /mnt/
Make a new place to keep /srv
sudo mkdir -p /mnt/local/srv
Copy home into the new location.
sudo cp -rp /home /mnt/local/
There are now some special files in /etc that programs want to write, we solve these as so..
Link mtab to dynamic copy
sudo rm /etc/mtab sudo ln -s /proc/self/mounts /etc/mtab
Link resolv.conf to a writable location
sudo apt-get install resolvconf sudo mv /etc/resolv.conf /mnt/local/resolv.conf sudo ln -s /var/local/resolv.conf /etc/resolv.conf
Remove /etc/network/run and reconfigure ifupdown
sudo rm /etc/network/run sudo dpkg-reconfigure ifupdown
Now we modify the filesystem table.
use your favourite text editor to open /etc/fstab and make it look like this:
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults,ro 0 2 # added 'ro' to /boot options /dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1 # added 'ro' to / options # a swapfile is not a swap partition, no line here # You probably don't want swap if you're looking to ruggedise your pi, if you want one, use a swap file at /var/swap # use dphys-swapfile swap[on|off] for that tmpfs /tmp tmpfs nodev,nosuid,size=100M 0 0 # /tmp is a RAMdisk, here we dedicate 100MB of our RAM to /tmp /dev/mmcblk0p3 /var ext4 defaults,noatime 0 2 # this is /var /var/local/srv /srv none bind # this is /srv, which is actually a directory in /var /var/local/home /home none bind # this is /home, which is actually a directory in /var
Now reboot and you will be in read only mode:
If you need to make changes, like installing new packages, you can do it like so:
Enter read/write mode:
sudo mount -o remount,rw / sudo mount -o remount,rw /boot
Make your changes, eg:
sudo raspi-config sudo apt-get install vim
Return to read-only mode:
sudo mount -o remount,ro /boot sudo mount -o remount,ro /
Installing your own code
If you run software on your pi that you wrote, like something that runs in your home directory, or a cloned git repo; you probably want it to be protected by read only mode. Your home is no good as it is read/write. Follow these guidelines to make your software rugged too:
- Copy your project to a directory in /opt, like /opt/bracken/my-project/my-project.py (remember to go to read/write mode to do this).
- If it's a git repository, clone it in /opt
- If your program writes files you want to keep, put them in /var, like /var/my-project/database.db
- If your program writes temporary files put them in /tmp, this doesn't write to the SD card at all.
- Put your logs in /var somewhere. Or better yet, use the system logger. Research 'syslog' in whatever programming language you use. Or start your program using a systemd service file, this will put anything you print into the system log.