Tuesday, November 14, 2017

Make your Raspberry Pi read-only for reducing SD wear/corruption

Everyone using Raspberry Pi's knows that SD cards are actually not made to serve as storage, especially when storage intensive applications (e.g. database, log server...) are being put in-there. To limit this SD wearing (which will lead to SD  corruption at some point), you can put Raspian in a read-only mode and only swith to read-write when really needed.

All kudos go to this blog for the excellent write up. I assume you have an RPi3 with Wheezy installed onto it. All commands are executed as root.

Update your RPi

Make yourself root, update your Raspian and reboot.
su -
apt-get update && apt-get upgrade
reboot

Remove some unwanted packages

apt-get remove --purge wolfram-engine triggerhappy anacron dphys-swapfile xserver-common lightdm
insserv -r x11-common; apt-get autoremove --purge
Replace the Rsyslog with the Busybox one
apt-get install busybox-syslogd; dpkg --purge rsyslog

Disable swap and filesystem check and set it to read-only

Edit the file: /boot/cmdline.txt and add the three words
fastboot noswap ro

Move some system files to the temp filesystem

rm -rf /var/lib/dhcp/ /var/run /var/spool /var/lock /etc/resolv.conf
ln -s /tmp /var/lib/dhcp
ln -s /tmp /var/run
ln -s /tmp /var/spool
ln -s /tmp /var/lock
touch /tmp/dhcpcd.resolv.conf; ln -s /tmp/dhcpcd.resolv.conf /etc/resolv.conf

Change the dhcpd lock file to the temp filesystem
vi /etc/systemd/system/dhcpcd5
And be sure to change the line with PIDFile=/run/dhcpcd.pid to PIDFile=/var/run/dhcpcd.pid

On Debian Jessie and Wheezy move random-seed to a writable location
rm /var/lib/systemd/random-seed
ln -s /tmp/random-seed /var/lib/systemd/random-seed
Since this file is on tmpfs, it will not be created upon reboot, but we can still do this with some magic of the systemd system service.
To create file on the tmp area at bootup before starting the random-seed service, just edit the file service file to add a pre-command to execute:
vi /lib/systemd/system/systemd-random-seed.service
Add the line: ExecStartPre=/bin/echo "" >/tmp/random-seed under the service section.

Do not use touch instead of echo, it won’t work because we'll be checking a read-only filesystem.
Execute the following to tell systemd we made changes.
systemctl daemon-reload

Setup the Internet clock sync

If (still) needed install NTP
apt-get install ntp
And be sure to configure your time zone, with raspi-config tool.
raspi-config
Then go to menu "Internationalisation Options" and change "Change Timezone" and select your time zone.

Edit the hourly cron script that saves the clock every hour

vi /etc/cron.hourly/fake-hwclock
And change it to allow saving the clock.
#!/bin/sh
#
# Simple cron script - save the current clock periodically in case of
# a power failure or other crash

if (command -v fake-hwclock >/dev/null 2>&1) ; then
  mount -o remount,rw /
  fake-hwclock save
  mount -o remount,ro /
fi

Edit the file /etc/ntp.conf and set to redirect driftfile to the writable zone /var/tmp
vi /etc/ntp.conf

Remove some startup scripts and edit fstab

insserv -r bootlogs; insserv -r console-setup
Edit fstab and add the ro option. Add the tmpfs parts as well.
vi /etc/fstab

tmpfs           /tmp            tmpfs   nosuid,nodev            0       0
tmpfs           /var/log        tmpfs   nosuid,nodev            0       0
tmpfs           /var/tmp        tmpfs   nosuid,nodev            0       0

Reboot

reboot

If all went fine, you're pi will be up again. Test if the filesystem is read-only now.

Switching from read-only mode to read-write and back

Now you’re in read-only mode, it’s fine and safe, but if you need to install, write or modify files, upgrade, or whatever that need write access, you'll need to be able to do this.

To set system to read-write:
mount -o remount,rw /
And to set it back to read-only:
mount -o remount,ro /
If you want to have two simple commands like: ro for setting mode to read-only and: rw to enable read-write mode. I also want to know on which mode I am in, on the command prompt.

Add fancy indicating features

Edit the file bash.bashrc
vi /etc/bash.bashrc
At the end add the following lines:
# set variable identifying the filesystem you work in (used in the prompt below)
set_bash_prompt(){
    fs_mode=$(mount | sed -n -e "s/^\/dev\/.* on \/ .*(\(r[w|o]\).*/\1/p")
    PS1='\[\033[01;32m\]\u@\h${fs_mode:+($fs_mode)}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
}

alias ro='sudo mount -o remount,ro / ; sudo mount -o remount,ro /boot'
alias rw='sudo mount -o remount,rw / ; sudo mount -o remount,rw /boot'

# setup fancy prompt"
PROMPT_COMMAND=set_bash_prompt

Execute this new file and look at the magic! The prompt has changed and shows the file system mode.
. /etc/bash.bashrc
Test by typing ro or rw to switch between modes.

Use logout to save history and force read-only mode

To be sure to avoid setting back to read-only at logout, add the following line to the file
/etc/bash.bash_logout. (maybe you'll need to create it)
vi /etc/bash.bash_logout
Add:
mount -o remount,rw /
history -a
fake-hwclock save
mount -o remount,ro /
mount -o remount,ro /boot



No comments:

Post a Comment