Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jayme-github/721a3bc24ea872f932dfbb875a158d4c to your computer and use it in GitHub Desktop.
Save jayme-github/721a3bc24ea872f932dfbb875a158d4c to your computer and use it in GitHub Desktop.

Installing Debian on btrfs subvolume

Install debian as usual:

  • EFI partition ~256M, boot, esp flags
  • ext2 boot partition ~512M
  • luks cyrpt volume
    • LVM pv
      • swap ~5G
      • btrfs

When the installation is finished, boot into SystemRescueCD.

In SystemRescueCD

Mount Debian filesystem:

mkdir /mnt/btrfs/
cryptsetup luksOpen /dev/nvme0n1p3 crypt
mount /dev/<VG Name>/btrfs /mnt/btrfs/

Create the subvolume "@". This follows ZFS "@-Naming" for subfolumes and is similar to the Ubuntu-specific subvolume layout (https://help.ubuntu.com/community/btrfs).

btrfs subvol create /mnt/btrfs/@

To check that the subvolume was created:

btrfs subvolume list /mnt/btrfs/

The output should be something like:

ID 268 gen 4624 top level 5 path @

Move all data to the newly created subvolume:

cd /mnt/btrfs
ls -1 | egrep -v '@|home' | while read d; do mv "$d" @/; done

Create a subvolume for /home the same way:

btrfs subvol create /mnt/btrfs/@home

Then move /home to the subvolume and created a mountpoint in @ subvolume:

mv home/* @home/
rmdir home
mkdir @/home

Everything should be moved into the subvolumes now.

btrfs subvolume list /mnt/btrfs/
ls -l /mnt/btrfs/

The output should be like:

ID 268 gen 4624 top level 5 path @
ID 426 gen 5355 top level 5 path @home

total 0
drwxr-xr-x 1 root root 204 Jul 16 02:26 @
drwxr-xr-x 1 root root 14 Jul 16 18:51 @home

Alter the fstab (/mnt/btrfs/@/etc/fstab) and add a line for /home, like:

/dev/mapper/<VG Name>-btrfs  /home  btrfs  noatime,ssd,discard,subvol=@home  0  0

In order to be able to boot into Debian, temporarily set the @ subvolume as default:

btrfs subvolume set-default 268 /mnt/btrfs/

The number "268" is the ID of the @ subvolume, as seen in the btrfs subvolume list output above.

Reboot to Debian:

umount /mnt/btrfs
vgchange -an <VG Name>
cryptsetup luksClose crypt
shutdown -r now

Grub2 settings

In Debian, change the default subvolume back to the top level volume. Otherwise the grub setup would break after the next update-grub. The top level subvolume always has the ID 5.

Mount the toplevel subvolume:

mkdir /mnt/btrfs/
mount -o subvolid=5 /dev/mapper/<VG Name>-btrfs /mnt/btrfs/

Change the default subvolume back to ID 5:

btrfs subvolume set-default 5 /mnt/btrfs/
umount /mnt/btrfs

Now it's possible to update grub configuration. The update-grub script correctly detects that the system is using the "@" btrfs subvolume and updates the /boot/grub/grub.cfg accordingly. That's the reason why it's not possible to continue using the "@" subvolume as default subvolume (with "set-default 268") instead of the top level volume. The /boot/grub/grub.cfg would have a configuration like "linux /@/boot/vmlinuz" but there is no other "@" subvolume in the "@" subvolume and thus the path would be incorrect.

Update grub and check that /boot/grub/grub.cfg was updated correctly:

update-grub
grep '@' /boot/grub/grub.cfg

The output should look like:

linux   /vmlinuz-4.19.0-2-amd64 root=/dev/mapper/<VG Name>-btrfs ro rootflags=subvol=@  quiet
      linux   /vmlinuz-4.19.0-2-amd64 root=/dev/mapper/<VG Name>-btrfs ro rootflags=subvol=@  quiet
      linux   /vmlinuz-4.19.0-2-amd64 root=/dev/mapper/<VG Name>-btrfs ro single rootflags=subvol=@

Reinstall grub to the root disk:

grub-install /dev/nvme0n1

Final touch

Alter the "/" entry in /etc/fstab to include the subvol=@ mount option, like:

UUID=4577942d-0841-42e9-a2f3-3d04b91ff2d5  /  btrfs  noatime,ssd,discard,subvol=@  0  0

Reboot.

Automatic snapshots with snapper

Install snapper and create default configs for snapshotting root and home filesystem/subvolume:

apt install snapper
systemctl disable snapper-boot.timer snapper-cleanup.timer snapper-timeline.timer

snapper -c root create-config /
snapper -c home create-config /home

This creates a new subvolume “.snapshots” at the root of the specified subvolume. Snapper has a utility to help you roll back; however, it is inherently flawed and can mess up your file system layout due to how it rolls back.

To avoid this, replace the created subvolumes with ones "outside" of the subvolume to snapshot.

btrfs subvolume delete @/.snapshots
btrfs subvolume delete @home/.snapshots

mkdir /mnt/btrfs/snapshots
btrfs subvolume create /mnt/btrfs/snapshots/@
btrfs subvolume create /mnt/btrfs/snapshots/@home

mkdir /.snapshots /home/.snapshots

Setup the fstab to mount the snapshot subvolumes to the newly created mount points:

# Snapshot subvolumes
UUID=05eccea6-9ca7-4015-83ed-50e89b1bc98f       /.snapshots             btrfs   noatime,ssd,discard,subvol=snapshots/@         0       0
UUID=05eccea6-9ca7-4015-83ed-50e89b1bc98f       /home/.snapshots        btrfs   noatime,ssd,discard,subvol=snapshots/@home     0       0

Mount snapshot subvolumes

mount /.snapshots/
mount /home/.snapshots/

Edit the snapper configs as needed (/etc/snapper/configs/*). Maybe you want to disable snapshots per apt install/ugrade in /etc/default/snapper.

Enable and start snapper:

systemctl enable snapper-boot.timer snapper-cleanup.timer snapper-timeline.timer
systemctl start snapper-timeline.timer snapper-cleanup.timer

Restore / Rollback

To restore a snapshot. Delete the "source" subvolume and create a rw snapshot (e.g. subvolume) of the desired snapshot

btrfs subvolume delete /mnt/btrfs/@home
btrfs subvolume snapshot /mnt/btrfs/snapshots/@home/1/snapshot/ /mnt/btrfs/@home

Snapshot metadata is stored in the info.xml file of each sapshot, see cat /mnt/btrfs/snapshots/@home/1/info.xml:

<?xml version="1.0"?>
<snapshot>
  <type>single</type>
  <num>1</num>
  <date>2019-02-10 16:24:44</date>
  <description></description>
  <cleanup>number</cleanup>
</snapshot>

This can also be done with root filesystem snapshots (via SystemRescueCD).

Thanks

This is a copy/clone/backup/mixture of great articles at:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment