Btrfs Formatted USB Key with Debian
Contents
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")
See also
- Is not btrfs about to replace our main live tools like squashfs, lzma, aufs, ... ? November 2010 thread on the debian-live mailing list
- Getting Started (btrfs Wiki) (read on 2011-05-03)
- SnapBtr (btrfs Wiki) (read on 2011-05-03)
- Installing Arch Linux onto a GPT partitioned, btrfs root SSD on a legacy BIOS system (as read on 2011-05-01)
- Booting from a btrfs filesystem in a GPT-partitioned USB flash drive attached to a non-EFI system (read on 2011-05-01)
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é.