Installing Debian on a Btrfs subvolume with LVM on LUKS

My colleague Pim recently did a great write-up on how to do a safe in-place upgrade to a slim Debian stretch running i3 using debootstrap (a tool which will install a Debian base system into a subdirectory of another, already installed system). However, what if you want to do a clean install from scratch to achieve this? Of course you can run a Debian-based live USB and then follow his debootstrap steps, using something like this to do all of the partitioning and other plumbing yourself. Other options include following these steps (from 2015, didn't seem to work for me, maybe because I needed it with LVM on LUKS), however beware that this does not include LUKS nor LVM on LUKS for Linux disk encryption.

People that know me know that I try to be a pragmatist, and since I am not super experienced with running debootstrap from either a live USB or the Debian Installer USB (should be possible) I wanted to try out another way for my clean install. Inspired by these other tutorials I came up with the following step-by-step guide for my own reference later on:

  1. Create a bootable Debian USB from the non-free netinstall image (unfortunately I need non-free drivers)
  2. Boot the machine from this USB drive and follow the steps from the Debian (non-graphical) Installer (I should look into preseeding)
  3. At the Partition disks step, choose Guided - use entire disk and set up encrypted LVM as partitioning method
  4. Make sure to pick the right disk, and not your USB drive
  5. Since I currently want to create only 1 Btrfs subvolume (root/@) I will pick All files in one partition as partitioning scheme
  6. Continue with setting up your LUKS encryption key, but halt for a second at the overview of your currently configured partitions and mount points
  7. Modify the root LV filesystem to not use ext4 but btrfs instead, then finish partitioning and write changes to disk
  8. The Debian installer will install to the default Btrfs subvolume, which is undesirable as snapshots and subvolumes will be created inside the root filesystem. Instead we want to have a snapshots directory and a root subvolume (@) for the root filesystem. We will resolve this after the Debian Installer has finished installing to the default Btrfs subvolume and is booted.

While some other tutorials suggest that this should be resolved by manually creating a new subvolume and then mv'ing the data over, I don't like this as a mv across subvolumes is slow and cpu intensive with large directories, therefore it would be better to create a snapshot of the default subvolume. The steps afterwards are heavily borrowed from here:

So, we’ll create the layout for the new default subvolume:

# btrfs subvolume snapshot / /@
# mkdir /snapshots

As the contents under /@ will become the new root filesystem, do not make any changes to the current root filesystem until you have rebooted.

Edit /\@/etc/fstab so that the new root subvolume will be used on subsequent reboots. I.e. you will need to include subvol=@ under options, à la:

# <file system>        <mount point>  <type>  <options>               <dump>  <pass>
/dev/mapper/nc110--vg-root /              btrfs   defaults,subvol=@  0       1

In order to boot into the right subvolume one needs to set the default subvolume to be root. E.g. find the subvolume’s ID with:

# btrfs subvolume list /
ID 259 gen 3491 top level 5 path @

and set it as default with:

# btrfs subvolume set-default 259 /

Then restart to boot into your root subvolume. Note that a measure of success is that the /snapshots folder should be missing. Now, delete the contents of the old root in the default subvolume. To facilitate this, and the creation of new subvolumes/snapshots, make a mountpoint for the default subvolume:

# mkdir -p /mnt/btrfs/root/

and add it to /etc/fstab:

# <file system>        <mount point>     <type>  <options>                     <dump>  <pass>
/dev/mapper/nc110--vg-root /mnt/btrfs/root/  btrfs   defaults,noauto,subvolid=5    0       1

Then proceed via:

# mount /mnt/btrfs/root/
# cd /mnt/btrfs/root/
# ls snapshots/
# ls -1 /mnt/btrfs/root/ | egrep -v '@|snapshots' | xargs echo
# ls -1 /mnt/btrfs/root/ | egrep -v '@|snapshots' | xargs rm -rf
# umount /mnt/btrfs/root/

This is reportedly also possible without setting the default subvolume (set-default) or a rescue disk.

At this point, you are pretty much done and you can do whatever you usually do post-installing Debian. If you started the minimalist way (only select OpenSSH server and Standard system utilities when installing) your (wireless) networking will likely be broken at this point, these steps can help out. You can then follow the rest of the steps from Pim's write-up, use the previous diet-jessie script or figure everything out yourself.

Open dm-crypt container (existing LUKS+LVM partition) in Debian Installer

When it comes to disk partitioning before picking “manual” switch to another terminal, e.g. <Ctrl>+<Alt>+<F2>, <Return>.

# anna-install cryptsetup-udeb partman-crypto-dm crypto-dm-modules crypto-modules
# depmod -a
# cryptsetup luksOpen /dev/sda5 cryptroot
# vgscan
# vgs
# vgchange -ay nc110-vg
# lvs

Switch back to the installer terminal by pressing <Ctrl>+<Alt>+<F1> (which will list LVM your current LVM volumes now). Special thanks to these posts.

Debian Installer tricks

I don't think I can do a better write-up than the one found here.


comments powered by Disqus