Read-only Slitaz using aufs

As SliTaz provides a perfect base for embeded-like systems I used it for another MPD Client. The computer resists behind my stereo and gets its power from it. So when switching off the stereo the computer loses power too which causes a not unmounted filesystem. I didn’t like that and thought of live CDs where the real filesystem (the iso) is mounted on top (overlay) of a ram-filesystem.

This should be possible using not an ISO (loop/cloop) based filesystem but also an ext2/3/4 filesystem. A short google search showed me http://wiki.ubuntuusers.de/Nur-Lesen_Root-Dateisystem_mit_aufs which is exactly the solution I was looking for. I only had to adopt it on SliTaz.

The Slitaz way is more complicated since I don’t know of a SliTaz package that offers initrd creation functionality so you have to do this all by your own, please follow these  instructions:

  • extract an exisiting initrd (use the one that comes with any SliTaz ISO)  “cat rootfs.gz | lzma -d -c | cpio -i”
  • install aufs kernel module (tazpkg install linux-aufs)
  • remove all module branches from the initrd (rm -rf lib/modules/*)
  • copy all kernel modules of the running kernel to it (cp -ax /lib/modules`uname -r` lib/modules)
  • copy the attached init (see below) into initrd
  • make it executable (chmod 0755 init)
  • repack it (find . -print | cpio -o -H newc | lzma -c –best >../aufsrootfs.gz)
  • modify the bootloader by passing the initrd and adding aufs=tmpfs to the kernel parameters

Init comes with two scripts that allows you to remount the underlying root partition rw. So you’re able to change the content of the filesystem (e.g. for running updates) but beware: If you’ll upgrade the kernel you have to repack the initrd!

Have fun!

This is the init you have to use instead of the existing one:

#! /bin/sh

export aufs

mount -t proc proc /proc
mount -t sysfs sysfs /sys

for x in $(cat /proc/cmdline); do
case $x in
root=*)
ROOTNAME=${x#root=}
;;
aufs=*)
aufs=${x#aufs=}
case $aufs in
tmpfs-debug)
aufs=tmpfs
aufsdebug=1
;;
esac
;;
esac
done

echo
echo “root-aufs: Setting up aufs on ${ROOTNAME} as root file system ”
echo

modprobe -q aufs || insmod /lib/modules/`uname -r`/kernel/fs/aufs/aufs.ko.gz
if [ $? -ne 0 ]; then
echo    root-aufs error: Failed to load aufs module
exit 0
fi

#make the mount points on the init root file system
mkdir /aufs
mkdir /rw
mkdir /ro

# mount the temp file system and move real root out of the way
mount -t tmpfs aufs-tmpfs /rw
mount ${ROOTNAME} /ro
if [ $? -ne 0 ]; then
echo “root-aufs error: ${ROOTNAME}  failed to move to /ro”
exit 0
fi

mount -t aufs -o dirs=/rw:/ro=ro aufs /aufs
if [ $? -ne 0 ]; then
echo    root-aufs error:      Failed to mount /aufs files system
exit 0
fi

#test for mount points on aufs file system
[  -d /aufs/ro ] || mkdir /aufs/ro
[  -d /aufs/rw ] || mkdir /aufs/rw

# the real root file system is hidden on /ro of the init file system.  move it to /ro
mount -omove /ro /aufs/ro
if [ $? -ne 0 ]; then
echo    root-aufs error:      Failed to move /ro /aufs/ro
exit 0
fi

# tmpfs file system is hidden on /rw
mount -omove /rw /aufs/rw
if [ $? -ne 0 ]; then
echo    root-aufs error:      Failed to move /rw /aufs/rw
exit 0
fi

#Add the comment block to fstab
cat <<EOF >/aufs/etc/fstab
#
#  $0 has mounted the root file system in ram
#
#  This fstab is in ram and the real fstab can be found /ro/etc/fstab
#  The root file system ‘ / ‘ has been removed.
EOF

#remove root from fstab
cat /aufs/ro/etc/fstab|grep -v ‘ / ‘ >>/aufs/etc/fstab

# add the read only file system to fstab
#ROOTTYPE=$(cat /proc/mounts|grep ${ROOT}|cut -d’ ‘ -f3)
#ROOTOPTIONS=$(cat /proc/mounts|grep ${ROOT}|cut -d’ ‘ -f4)
#echo ${ROOT} /ro $ROOTTYPE $ROOTOPTIONS 0 0 >>/aufs/etc/fstab

# S22mount on debian systems is not mounting  /ro correctly after boot
# add to rc.local to correct what you see from df
#replace last case of exit with #exit
#cat /aufs/ro/etc/rc.local|sed ‘s/\(.*\)exit/\1\#exit/’ >/aufs/etc/rc.local
#echo mount -f  /ro >>/aufs/etc/rc.local

# add back the root file system. mtab seems to be created by one of the init proceses.
#echo “echo aufs / aufs rw,xino=/rw/.aufs.xino,br:/rw=rw:/ro=ro 0 0 >>/etc/mtab” >>/aufs/etc/rc.local
#echo “echo aufs-tmpfs /rw tmpfs rw 0 0 >>/etc/mtab” >>/aufs/etc/rc.local
#echo exit 0 >>/aufs/etc/rc.local

#fix permissions
chmod 755 /aufs

#build remountrw
echo \#!/bin/sh >/aufs/bin/remountrw
echo mount -o remount,rw ${ROOT} >>/aufs/usr/bin/remountrw
chmod 0700 /aufs/bin/remountrw

#build remountro
echo \#!/bin/sh >/aufs/bin/remountro
echo mount -o remount,ro ${ROOT} >>/aufs/usr/bin/remountro
chmod 0700 /aufs/bin/remountro

umount /sys
umount /proc

# remount ro
mount -oremount,ro /aufs

echo -e “\33[70G[ \33[1;33mOK\33[0;39m ]”
exec /sbin/switch_root /aufs /sbin/init

For reference, this is my grub menu.lst with the old (normal boot) and the new (aufs read only boot) entry:

[…]

title SliTaz GNU/Linux (Kernel 2.6.37-slitaz)
root (hd0,0)
kernel /boot/vmlinuz-2.6.37-slitaz root=/dev/hda1

title SliTaz GNU/Linux (Kernel 2.6.37-slitaz) (AUFS)
root (hd0,0)
kernel /boot/vmlinuz-2.6.37-slitaz root=/dev/hda1 aufs=tmpfs
initrd /boot/aufsrootfs.gz

Advertisements
This entry was posted in Linux, MPD. Bookmark the permalink.

8 Responses to Read-only Slitaz using aufs

  1. rxd says:

    This is nice, would you mind sharing the finish iso?
    root aufs plus pxe or wifi boot makes a perfect LAN.
    Just enough to boot with X, and all the apps on the network
    *.sfs or *.sqx where i can just add or del from root aufs.

    • Peter Fichtner says:

      Sorry for the long delay, I’ve been very busy the last days.
      Perhaps it’s possible using SliTaz’s Flavors? Have you played around with flavours yet?
      Do you know a possibility to create initrds inside SliTaz (like ubuntu does this)?

      I would prefer this over generating and distributing “static” isos.

      • rxd says:

        Yes i have created before my custom root aufs slitaz, slitaz is good my only problem
        is, it has limited support for say network drivers wired/wireless plus limited updated applications.
        So i switched to ubuntu, i modified initrd.lz, the init script and casper script so i get the root aufs upon chroot to second stage booting and putting files on the ntfs partition just like a frugal install. Its a read only system that i can add sqx files to my root aufs. A usb stick is where i boot with grub2 with parameters fdir=(directory on the ntfs partion) fdev=(/dev/xxx device where the files reside), once it has booted i can now take out my usb stick without problems. I feel this is the safest way to run linux as read only system than installing linux using the physical ext3/ext4 partition.

  2. Stefan says:

    i found out that not all of your commands are working properly with my slitaz version…

    extract an exisiting initrd:
    “cat rootfs.gz | lzma -d -c | cpio -i” -> doesn’t work for me!
    in Slitaz forum I’ve found another command to extract rootfs.gz, that works fine:
    (zcat rootfs.gz 2>/dev/null || lzma d rootfs.gz -so) | cpio -id

    repack initrd:
    (find . -print | cpio -o -H newc | lzma -c –best >../aufsrootfs.gz) -> seems to work, but I in fact i get an initrd, that i can’t extract again…
    so I’m looking for another solution to repack initrd…

    • rrsuj says:

      It worked for me –

      $ find . | cpio -H newc -o > ../initramfs.cpio
      $ cd ..
      $ cat initramfs.cpio | gzip > initramfs.igz

      Then-
      title SliTaz GNU/Linux (Kernel 2.6.37-slitaz) (AUFS)
      root (hd0,0)
      kernel /boot/vmlinuz-2.6.37-slitaz root=/dev/hda1 aufs=tmpfs
      initrd /boot/initramfs.igz

  3. rrsuj says:

    Hi,
    I did all steps, but now my linux boot into text mode, how can I boot in graphical mode?
    I did “init 5”, but it reports that “init: must be run as PID 1”, I did also “su” to enter root user, but same result. What should I do now?

    • Peter Fichtner says:

      The script I posted was based on the text-only init-script so I am sorry that I am unable to give you support for that. Perhaps you use your working init-script as your base and patch that script by the needed lines to get aufs work here

      • rrsuj says:

        Hi,
        I tried a lot to patch my init script, but no success 😦

        So here I copied my fresh init script, please tell me where to put all your above code to work.
        Also please correct me if I am wrong- as far as I understand, when the readonly linux will boot, I think I can do “write” operations on the tmpfs (non-persistent) file system, is it right?

        the init script:

        #!/bin/sh

        success()
        {
        cat > /dev/shm/init
        [ -d /proc/sys ] && umount /proc
        echo -e “\33[70G[ \33[1;32mOK\33[0;39m ]”
        exit
        }

        launch_init()
        {
        mount –move /dev/pts /mnt/dev/pts
        mount –move /dev/shm /mnt/dev/shm
        success <<EOT
        exec /sbin/switch_root mnt /sbin/init
        EOT
        }

        failed()
        {
        umount /proc
        echo -e "\33[70G[ \33[1;31mFailed\33[0;39m ]"
        }

        try_init()
        {
        if [ ! -d /mnt/etc ] && grep -q cryptoroot= /proc/cmdline; then
        modprobe dm-mod
        modprobe dm-crypt
        modprobe aes-i586
        root="$(sed 's/.*cryptoroot=\([^ ]*\).*/\1/' /dev/null; then
        cryptsetup luksOpen $root $dmlabel
        else
        read -s -t 60 -p “Pass phrase : ” passphrase
        key=$(echo $passphrase | hashalot -x -n 32 sha512)
        blocks=$(cat $(find /sys/block | grep /$dev/size))
        echo 0 $blocks crypt aes-plain $key 0 $root 0 | \
        dmsetup create $dmlabel
        fi
        mount /dev/mapper/$dmlabel /mnt
        fi
        grep -q subroot= /proc/cmdline && return
        grep -q loopfs= /proc/cmdline && return
        if [ -d /mnt/etc ]; then
        umount /sys
        [ -n “$1″ ] && for i in $@ ; do
        cp -a $i /mnt$(dirname $i)
        done
        mount /mnt -o remount,ro
        launch_init
        fi
        failed
        }

        mount_mapper()
        {
        mount $root /mnt
        try_init /dev/mapper $@
        }

        lvmsetup()
        {
        grep -q lvmroot= /proc/cmdline || return 1
        modprobe dm-mod
        vgscan –ignorelockingfailure
        vgchange -ay –ignorelockingfailure
        root=”/dev/mapper/$(sed ‘s/.*lvmroot=\([^ ]*\).*/\1/’ < /proc/cmdline)"
        return 0
        }

        load_raid()
        {
        while read line; do
        case "$line" in
        *raid10*) modprobe raid10 ;;
        *raid0*) modprobe raid0 ;;
        *raid1*) modprobe raid1 ;;
        *raid[456]*) modprobe raid456 ;;
        *mirror*) modprobe dm-mirror ;;
        esac
        done
        }

        if [ "$1" != "logged" ]; then
        mount -t devpts devpts /dev/pts
        mount -t tmpfs tmpfs /dev/shm
        script -qc '/init logged' /dev/shm/boot.log
        . /dev/shm/init
        else
        mount -t proc proc /proc
        mount -t sysfs sysfs /sys
        if grep -q dmraid= /proc/cmdline; then
        root="$(sed 's/.*dmraid=\([^ ]*\).*/\1/' < /proc/cmdline)"
        echo -n "Switching / to dmraid $root…"
        dmraid -s | grep ^type | awk '{ print $3 }' | load_raid
        case "$root" in
        /dev/*);;
        *) root=/dev/mapper/$(dmraid -s|grep ^name|awk '{print $3}')p${root#p};;
        esac
        dmraid -ay
        lvmsetup
        mount_mapper
        fi
        if grep -q softraid= /proc/cmdline; then
        root="$(sed 's/.*softraid=\([^ ]*\).*/\1/' /etc/mdadm.conf
        grep -qs ” $root ” /etc/mdadm.conf ||
        root=$(awk ‘/dev.md/ { print $2; exit }’ < /etc/mdadm.conf)
        grep level=raid /etc/mdadm.conf | load_raid
        for i in 1 2 3 4 5 6 7 8 9; do
        sleep $i
        mdadm –assemble –scan
        grep -qs ': active' /proc/mdstat && break
        done
        lvmsetup
        mount_mapper /etc/mdadm.conf
        fi
        if lvmsetup; then
        echo -n "Switching / to lvm $root…"
        mount_mapper
        fi
        if grep -q mount= /proc/cmdline; then
        root="$(sed 's/.*mount=\([^ ]*\).*/\1/' < /proc/cmdline)"
        dev=$(blkid | grep $root | sed 's/:.*//;q')
        [ "$dev" = "$root" ] || root="$dev ($root)"
        echo "Mounting $root …"
        if ! mount $dev /mnt; then
        if echo $dev | grep -q "/dev/sd"; then
        delay=`cat /sys/module/usb_storage/parameters/delay_use`
        delay=$((1+$delay))
        echo -n "sleep for $delay seconds…"
        sleep $delay
        fi
        mount $dev /mnt
        fi
        grep -q posixovl /proc/cmdline &&
        echo "Mounting posixovl.." &&
        mount.posixovl /mnt
        fi
        if grep -q loopfs= /proc/cmdline; then
        loopfs="$(sed 's/.*loopfs=\([^ ]*\).*/\1/' /dev/null
        fi
        if grep -q bindfs= /proc/cmdline; then
        bind=”$(sed ‘s/.*bindfs=\([^ ]*\).*/\1/’ < /proc/cmdline)"
        echo "Binding ${bind/,/ to } …"
        mount –bind /mnt/${bind%,*} /mnt/${bind%,*}/${bind#*,}
        fi
        grep -q cryptoroot= /proc/cmdline && try_init
        umount /sys
        if grep -q subroot= /proc/cmdline; then
        subroot="/$(sed 's/.*subroot=\([^ ]*\).*/\1/' \(/lib/l[^ ]*\).*|\1|;/^\//!d’) /usr/sbin/chroot /mnt$shm
        success <<EOT
        export LD_LIBRARY_PATH=$shm:/lib
        exec /sbin/switch_root mnt $shm/$(cd /mnt$shm ; ls ld-*) $shm/chroot $subroot /sbin/init
        EOT
        fi
        echo -n "Switching / to tmpfs"
        size="$(grep rootfssize= /dev/shm/init
        if [ $free -lt 100 ] || ! mount -t tmpfs $size tmpfs /mnt; then
        echo -e “\33[70G[ \33[1;33mSkipped\33[0;39m]”
        exit
        fi
        for i in $(ls -ar /); do
        case “$i” in
        .|..) ;;
        mnt) mkdir /mnt/mnt;;
        usr|var) mv /$i /mnt ;;
        *) if ! cp -a /$i /mnt 2> /dev/null; then
        failed
        umount /mnt
        exit
        fi;;
        esac
        done
        launch_init
        fi

        Please help me to run the readonly linux with graphical mode. Thank you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s