Having had a Seagate Dockstar with console access, I installed Debian squeeze onto it. As a starting point to make it run on read-only root, I used this excellent article 1 by Jeff Doozan. The basic strategy involves creating a script that, upon every boot, mounts the necessary writable directories as a tmpfs. I quote the script by Jeff 2 here (kudos to Jeff!)
#!/bin/bash
DIRS="/tmp /var/log /var/run /var/lock /var/tmp /var/lib/urandom /var/lib/dhcp /etc/network/run"
for DIR in $DIRS; do
echo "Mounting $DIR as tmpfs"
mount -n -t tmpfs tmpfs $DIR
if [ -d "$DIR-saved" ]; then
echo "Restoring $DIR-saved to $DIR"
tar -C "$DIR-saved" -cf - ./ | tar -C "$DIR" -xpf -
fi
done
echo "nameserver 4.2.2.1" > /var/tmp/resolv.conf
touch /var/lib/dhcp/dhcpd.leases
exec /sbin/init
Save the lines above as a script called /sbin/init-ro on your target rootfs and make it executable.
chmod 755 /sbin/init-ro
In order to use this script during boot-time, you have to prepare the system rootfs a bit (all quoted from Jeff's script 2 (adapt $ROOT
to the actual location of your mounted rootfs).
# Configure dhcp-client to write resolv.conf to /tmp instead of /etc
sed -i 's/\/etc\/resolv.conf/\/var\/tmp\/resolv.conf/' $ROOT/sbin/dhclient-script > /dev/null 2>&1
rm $ROOT/etc/resolv.conf
ln -s /var/tmp/resolv.conf $ROOT/etc/resolv.conf
# make /etc/network/run/ a symlink to /tmp/network/
rm -rf $ROOT/etc/network/run
ln -s /var/tmp/network $ROOT/etc/network/run
# Fixes from http://wiki.debian.org/ReadonlyRoot
rm $ROOT/etc/blkid.tab > /dev/null 2>&1
ln -s /dev/null $ROOT/etc/blkid.tab
rm $ROOT/etc/mtab > /dev/null 2>&1
ln -s /proc/mounts $ROOT/etc/mtab
rm $ROOT/etc/rcS.d/S12udev-mtab
rm -rf $ROOT/var/log/*
After having the rootfs prepared like above, you can mount the rootfs read-only in /etc/fstab (replace ext2 with the filesystem you're using or just use rootfs instead).
/dev/root / ext2 noatime,ro 0 1
Finally, you have to append the following to your kernel parameters (i.e. in /boot/cmdline.txt on Raspi) in order to run the script before the actual /sbin/init. (the following is just an example of root and rootdelay parameters. the important part that has to be appended to the line in cmdline.txt is init=/sbin/init-ro
.)
root=/dev/mmcblk0p2 rootdelay=2 init=/sbin/init-ro
But be aware that for any software requiring write-access on the rootfs you have to mount the appropriate tmpfs locations or write to external storage.