Btrfs Formatted USB Key with Debian

A live USB key is a nice thing to have in your handbag: as a recovery system, as a way to run a proper system on a PC that is still windows-encumbered, as a way to test new hardware. On the other hand, live distributions were created for read-only media, and using them on an usb-key can be limiting, expecially when it could be useful to keep the changes done on such a system.

Modern GNU/Linux distributions have integrated some improvements from live systems, expecially in the area of hardware recognition, and it is usually feasible to run them on a different PC than the one where it had been originally installed. This gives an idea: what about installing a plain Debian system on an USB key, check that it is able to boot and work even when the hardware changes, and use that instead of a live system?

Sometimes, however, it is useful to lose a the edits of a session: to keep this ability, the USB key is formatted as btrfs, using its snapshotting feature to keep a backup of previous sessions. This unluckily means that a bigger USB key is needed: with smaller keys ( < 4GB) you can probably expect to have about 1/4 of the space available for the system.

This is work in progress: the current status is an almost empty system that boots, allows login, and doesn't do anything nice with btrfs, yet.

HOWTO

Installation

I don't know whether btrfs is already supported in the debian installer, and I already have a (few) working linux system(s), so I've just used debootstrap from an Arch Linux installation.

The following commands should work in any distribution with btrfs support, and should be given as root.

Let's call the USB key /dev/sdb1, double check the real name on your system, of course. Start by creating a couple of mountpoints:

mkdir /mnt/usb-key
mkdir /mnt/debian

Create a single partition on you key using your tool of choice, and remember to set its bootable flag. Then, create a btrfs filesystem on the partition, with one subvolume called __active:

fdisk /dev/sdb
mkfs.btrfs -L 'debian' /dev/sdb1
mount /dev/sdb1 /mnt/usb-key
cd /mnt/usb-key
btrfs subvolume create __active
cd -

It seems that extlinux isn't able to find its configuration files in a subvolume, so we have to keep boot on the root one:

mkdir /mnt/usb-key/boot
mkdir /mnt/usb-key/__active/boot

mount the subvolume, and bind the above root to it:

mount -t btrfs -o subvol=__active /dev/sdb1 /mnt/debian
mount --bind /mnt/usb-key/boot /mnt/debian/boot

Debootstrap debian in the partition, then umount the root subvolume:

debootstrap --arch i386 squeeze /mnt/debian $DEBIAN_MIRROR
umount /mnt/debian/boot
umount /mnt/usb-key

Then enter the chroot and remount the boot from inside:

mount --bind /dev /mnt/debian/dev
mount --bind /proc /mnt/debian/proc
chroot /mnt/debian /bin/bash
mount /dev/sdb1 /mnt
mount --bind /mnt/boot /boot

Now, install debian in that partition, including kernel and bootloader. If you want to install additional programs you may of course add them to the apt-get line below:

apt-get update
apt-get install btrfs-tools linux-image-686 extlinux
extlinux --install /mnt/boot/extlinux/

Configure extlinux to let it know that the system is in a subvolume by editing /etc/default/extlinux and adding rootflags=subvol=__active to the EXTLINUX_PARAMETERS variable, so that it looks like:

EXTLINUX_PARAMETERS="ro quiet rootflags=subvol=__active"

in the same file add also root=/dev/disk/by-label/debian to EXTLINUX_ROOT:

EXTLINUX_ROOT="root=/dev/disk/by-label/debian"

Now use extlinux-update to update the extlinux configuration and copy a proper mbr to the key:

extlinux-update
cat /usr/lib/extlinux/mbr.bin > /dev/sdb

Edit /etc/fstab to mount the proper subvolume to /, and the root subvolume to a subdirectory of /mnt so that boot can be bind-mounted to allow kernel updates from the system, by adding the following lines:

/dev/disk/by-label/debian  /             btrfs  defaults,relatime,subvol=__active  0 0
/dev/disk/by-label/debian  /mnt/usb-key  btrfs  defaults,relatime  0 0
/mnt/usb-key/boot          /boot         none   rw,bind  0 0

don't forget to create the directory where the root subvolume is going to be mounted:

mkdir /mnt/usb-key

Finally, clear some space and exit the chroot:

apt-get clean
umount /boot
umount /mnt
exit
umount /mnt/debian/proc
umount /mnt/debian/dev
umount /mnt/debian

It seems that extlinux as installed by debian wants to look for the kernel in the / directory instead of /boot: let's satisfy it with a couple of symlinks (change the filenames as needed):

mount /dev/sdb1 /mnt/usb-b
cd /mnt/usb-b
ln -s boot/vmlinuz-2.6.32-5-686 vmlinuz-2.6.32-5-686
ln -s boot/initrd.img-2.6.32-5-686 initrd.img-2.6.32-5-686
cd -
umount /mnt/usb-b

remember to keep them updated when upgrading the kernel.

TODO

  • Automatical snapshotting (at boot? at shutdown)
  • Restore of a snapshot (at shutdown? "Forget changes")

Comments

From: lateo

Hi,

using you howto as a base, i made myself a sweet usb debian system.

attachment : a quite dirty but working solution to « extlinux as installed by debian wants to look for the kernel in the / directory instead of /boot ». i put it in /usr/local/bin then use it to upgrade the system.

regards,

Lateo.

#!/bin/bash


echo "Récupération des listes de paquets..."
aptitude -q=2 update
aptitude -r safe-upgrade


echo
echo "Traitement des éventuelles mises à jour du kernel..."
cd /mnt/subvolume/
kernels_dispo=$(ls boot | egrep 'vmlinuz|initrd')
for stuff in $kernels_dispo; do
        if [ ! -h $stuff ]; then
                echo "Ajout du lien symbolique pour "$stuff"..."
                ln -s /boot/$stuff .
        else
                echo "Le lien symbolique pour "$stuff" existe."
        fi
done
echo Terminé.
Send a comment: unless requested otherwise I may add it, or some extract, to this page.

Return to Top