Skip to content

Instantly share code, notes, and snippets.

@netj
Created September 14, 2011 12:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save netj/1216392 to your computer and use it in GitHub Desktop.
Save netj/1216392 to your computer and use it in GitHub Desktop.
init.d script for Debian read-only root filesystem
#! /bin/bash
# readonlyroot.sh -- Setup dirs on the tmpfs to keep the root partition read-only
# See-Also: http://roland.entierement.nu/pages/debian-on-soekris-howto.html
# Available-At: https://gist.github.com/1216392
#
# Place this file in /etc/init.d and run:
# sudo update-rc.d readonlyroot.sh start 04 S
#
# To maintain persistent data, place a file at /etc/cron.d/readonlyroot as:
# 0 * * * * root /etc/init.d/readonlyroot.sh save >/dev/null
#
### BEGIN INIT INFO
# Provides: readonlyroot
# Required-Start: mountdevsubfs
# Required-Stop:
# X-Start-Before: bootlogd
# Default-Start: S
# Default-Stop:
# Short-Description: Prepare read-only root filesystem.
# Description:
### END INIT INFO
set -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="read-only root"
PREFIX=/dev/shm
DIRS=(
/etc/network/run
/var/backups
/var/log
/var/lib/{dhcp,ntp,exim4,urandom,logrotate}
/var/spool/{cron,exim4/{db,input,msglog}}
/var/tmp
/var/cache/bind
)
FILES=(
/etc/adjtime
/etc/blkid.tab
)
MKDIRS=(
/var/spool/cron/{at{jobs,spool},crontabs}
/var/log/{exim4,news,apt,fsck}
)
TOUCHFILES=(
/var/log/exim4/mainlog
)
PERSIST=/var/persist
PERSISTPATHS=(
/var/backups
/var/spool
/var/lib/{dhcp,logrotate}
/var/cache/bind
)
case "$1" in
init)
echo -n "Initializing $DESC... "
for i in "${DIRS[@]}" "${FILES[@]}"; do
[ ! -L $i ] || [ x"`readlink $i`" != x${PREFIX}$i ] || continue
echo $i
mkdir -p `dirname ${PREFIX}$i`
mv -f $i ${PREFIX}$i || rm -rf $i
ln -sfn ${PREFIX}$i $i
done
echo "done."
;;
start)
echo -n "Setting up $DESC... "
# fix stuffs
mount -t tmpfs -o size=100k,mode=700 sudo /var/lib/sudo
# skeleton of $PREFIX
for i in "${DIRS[@]}" "${MKDIRS[@]}"
do mkdir -p ${PREFIX}$i
done
# files in $PREFIX
for i in "${TOUCHFILES[@]}"
do touch ${PREFIX}$i
done
# fix stuffs
chown Debian-exim:adm ${PREFIX}/var/log/exim4/mainlog
chown -R Debian-exim:adm ${PREFIX}/var/spool/exim4
chown daemon:daemon ${PREFIX}/var/spool/cron/at{jobs,spool}
chmod ug=rwx,o=,+t ${PREFIX}/var/spool/cron/at{jobs,spool}
chown root:crontab ${PREFIX}/var/spool/cron/crontabs
chmod ug=rwx,g-r,o=,+t ${PREFIX}/var/spool/cron/crontabs
chown ntp:ntp ${PREFIX}/var/lib/ntp
echo "done."
# load persistent data
"$0" load
;;
stop)
echo -n "Stopping $DESC... "
umount /var/lib/sudo
echo "done."
;;
load)
echo -n "Loading persistent data... "
cd "$PREFIX"
tar xzpf "$PERSIST"/current.tar.gz
echo "done."
;;
save)
echo -n "Saving persistent data... "
if [ -L "$PERSIST"/current.tar.gz ]; then
current=`readlink "$PERSIST"/current.tar.gz`
next=$((1 - ${current%.tar.gz})).tar.gz
else
next=0.tar.gz
fi
cd "$PREFIX"
fs=`df "$PERSIST" | tail -n +2 | sed 's/.*% *//' | head -n 1`
: ${fs:=/}
trap 'mount -o remount,ro "$fs"' EXIT
mount -o remount,rw "$fs"
mkdir -p "$PERSIST"
tar czf "$PERSIST"/$next "${PERSISTPATHS[@]#/}"
chown root:adm "$PERSIST"/$next
chmod ug=r,o= "$PERSIST"/$next
ln -sfn $next "$PERSIST"/current.tar.gz
sync
echo "done."
;;
*)
# echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|init|save|load}" >&2
exit 1
;;
esac
exit 0
@alexander-zimmermann
Copy link

Hi,

thank you for writing this script. It's very useful.

However, I've doubt that the script behave as you expect. At least in my environment I encounter a bug. In line 65 you move everything to /dev/shm, especially /etc/blkid.tab. Later on during the boot process, tmpfs is mounted over /dev/shm. At result, that the copied data is not available. The link /etc/blkid.tab -> /dev/shm/etc/blkid.tab points to nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment