Linux
Debian with Read-Only Root
Introduction
The descibed procedure shows how to install a Debian based minimal linux system with read-only root filesystem on, e.g. a CompactFlash (CF) card or USB drive.
For the installation you need an already running Debian system with an
architecture that is compatible with the architecture of the final system (e.g.,
a Debian on an amd64
PC, if the final system
is a thin client with amd64
or i686
architecture).
This system is required in order to prepare the CF card or USB drive. All of
the following steps are done under this system.
WARNING
The following steps are all done as user root
. You can easily
damage your running system with a wrong command. Be careful and understand
the instructions before trying them. USE ON YOUR OWN RISK!
Preparation of the Filesystem
The Debian system requires at least 512 MB. The USB drive has to be
partitioned and formated. Let us assume the drive is
/dev/sdd
. Of course, you will have to
change this to the appropriate device on your system.
WARNING: The next steps will destroy any data on your USB drive!
Partition /dev/sdd
, for example,
with fdisk or cfdisk:
- delete all existing partitions
- create a new, first primary partition (starting at the begining of the device); recommended size: at least 1 GB
- set the partition's system ID to 0x83
- set the bootable flag for this partition
Next, format the partition with the EXT2 filesystem. As the filesystem will be read-only, we do not gain anything using a journalling filesystem.
# mkfs.ext2 /dev/sdd1
Finally, mount the new filesystem:
# mount /dev/sdd1 /mnt
Installation of the System
Install the following tool:
# apt-get install debootstrap
The Debian system for the USB drive is now bootstrapped to a temporary
directory /scratch/deb
and then copied to
the USB drive mounted on
/mnt
:
# mkdir /scratch/deb # debootstrap --arch=amd64 wheezy /scratch/deb http://ftp.de.debian.org/debian # cp -a /scratch/deb/* /mnt
Basic Configuration
Now, several files under /etc
must be writable for a functional
system (see
ReadonlyRoot in the Debian Wiki)
as well as further directories under /
.
There are several ways how to solve this. One way is to resolve all the issues
for the files under /etc
manually as described in the Debian
Wiki. Another way is to transparently overlay an aufs
filesystem
as a writable layer and make /
appear writable (see
aufsRootFileSystemOnUsbFlash in the Ubuntu Documentation).
Any changes are held in RAM and lost on the next reboot.
Here, we use a mixture of these approaches and only use an aufs
filesystem for /etc
and /var
. This can be configured
as shown in the following.
First of all, the file /etc/mtab
normally needs
to be writable. As an alternative, it may be substituted by a symlink:
# rm /cf/etc/mtab # ln -s /proc/mounts /mnt/etc/mtab
Then, create the following file:
File: /mnt/etc/fstab
UUID=01234567-89ab-cdef-0123-456789abcdef / ext2 defaults,noatime,ro 0 0
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
Here, 01234567-89ab-cdef-0123-456789abcdef
has to be replaced by the block ID of /dev/sdd1
,
which can be read using:
# blkid /dev/sdd1
Create the following shell script, which will make /etc
and
/var
writable:
File: /mnt/etc/init.d/mountaufs.sh
#! /bin/sh ### BEGIN INIT INFO # Provides: mountaufs # Required-Start: mountall # Required-Stop: # Should-Start: # Default-Start: S # Default-Stop: # Short-Description: Mount aufs over /etc and /var. # Description: ### END INIT INFO PATH=/sbin:/bin . /lib/init/vars.sh . /lib/lsb/init-functions make_rw () { mkdir "/tmp/${1}" mount -t aufs -o "br:/tmp/${1}=rw:/${1}=ro" none "/${1}" } do_start () { make_rw etc make_rw var } case "$1" in start|"") do_start ;; status|restart|reload|force-reload) echo "Error: argument '$1' not supported" >&2 exit 3 ;; stop) # No-op ;; *) echo "Usage: mountaufs.sh [start|stop]" >&2 exit 3 ;; esac :
Make sure it is executable:
# chmod +x /mnt/etc/init.d/mountaufs.sh
Basic Network Configuration
The hostname of the system is set to
client
like this:
File: /mnt/etc/hostname
client
Static hostnames can be configured:
File: /mnt/etc/hosts
127.0.0.1 localhost ## the following line only, if the system will have a static IP: 223.1.2.99 client.example.com client ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts
The network interface configuration can be either static ...
File: /mnt/etc/network/interfaces
auto lo iface lo inet loopback allow-hotplug eth0 iface eth0 inet static address 223.1.2.99 netmask 255.255.255.0 network 223.1.2.0 broadcast 223.1.2.255 gateway 223.1.2.1 # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 223.1.2.1 dns-search example.com
File: /mnt/etc/resolv.conf.static
nameserver 223.1.2.1 search example.com
... or dynamic:
File: /mnt/etc/network/interfaces
auto lo iface lo inet loopback allow-hotplug eth0 iface eth0 inet dhcp
Installation of Kernel and Bootloader
We now change root to the bootstrapped system to install further packages, especially, the kernel and bootloader:
# mount -t proc proc /mnt/proc # mount -o bind /dev /mnt/dev # mount -o bind /sys /mnt/sys # LC_ALL="C" chroot /mnt /bin/bash
The installation is done as usual:
# apt-get update
# apt-get install linux-image-amd64 grub2 aufs-tools
# apt-get clean
During the installation of the grub2
package, it will
ask you where to install the bootloader. Answer with
/dev/sdd
.
If you did not check anything and skip the installation of the bootloader in the previous step, you can still manually install it:
# grub-install /dev/sdd
Finishing the Configuration
Activate the previously generated start script
/etc/init.d/mountaufs.sh
:
# update-rc.d mountaufs.sh enable
Finally, exit the chroot environment.
# exit # umount /mnt/proc # umount /mnt/dev # umount /mnt/sys # umount /mnt
In case you encounter problems
umount
ing /mnt
,
you might need to re-enter the USB drive system and stop processes
still accessing it. You can find such processes with:
# fuser -m /dev/sdd1
Done. The USB drive should now work in the thin client. Of course, you can also add further programs by changing root to the USB drive's filesystem.
Note: The current system has no root password.
You might want to add one in the change root environment with the
passwd
command.