Ubuntu Server 18.04 with proper btrfs

Btrfs is a wonderful filesystem that is fully compatible with ubuntu 18.04.

But unfortunatly, out-of-the-box, the installer doesn't come with a proper solution to setup a btrfs filesystem.

However, it is quite easy to make it by yourself.

What we will do is that we will follow the steps of the normal ubuntu server live installer and at the end of the install we will make the proper BTRFS setup.

Pre-requisites:

Step 1: Disk Partitionning

During the install, choose the partitioning that you want:

  • /dev/sda1 512M FAT32 flag:ESP,BOOT -> this will be our /boot/efi
  • /dev/sda2 XXXG btrfs -> this will be our btrfs / and any subvolume we like

Notes:

  1. I will use zram-config to create in memory compressed swap, so no swap partition here.
  2. Change XXX so you use your disk fully

Step 2: Do the install and wait for the message "Installation Complete" (but do not reboot)

just after the partitionning step, you arrive to the setup for the main user. Wait here for the message "Installation Complete"

Step 3: Open a terminal (Ctrl+Alt+F2) and fix the mess...

sudo -i
mount -l

identify the mounts in /target (in my case /dev/sda1)

unmount the /target/boot/efi for now

umount /target/boot/efi

create a subvolume for the root filesystem and for home

cd /target
btrfs subvolume create @
btrfs subvolume create @home

move the root tree to your newly created subvolume

mv -t @ b* d* e* h* i* l* m* o* p* r* s* t* u* v*

unmount the filesystem

cd /
umount /target

Step 3: mount again the filesystem and prepare for chroot

mount -o compress=lzo,ssd,noatime,nodiratime,space_cache,discard,subvol=@ /dev/sda2 /target
mount -o compress=lzo,ssd,noatime,nodiratime,space_cache,discard,subvol=@home /dev/sda2 /target/home
mount /dev/sda1 /target/boot/efi
mount --bind /proc /target/proc
mount --bind /dev /target/dev
mount --bind /sys /target/sys

Step 4: edit fstab

Fist, take a look at the UUID of your partitions, open another terminal and do:
lsblk -f
and replace UUID-OF-/DEV/SDA2 with your UUID
and replace UUID-OF-/DEV/SDA1 with your UUID

if you cannot find the UUID of your disks, use the one already available in your fstab

now chroot and edit fstab:

chroot /target
vi /etc/fstab

/etc/fstab:

/dev/disk/by-uuid/UUID-OF-/DEV/SDA2 / btrfs compress=lzo,noatime,nodiratime,space_cache,ssd,discard,subvol=@ 0 1  
/dev/disk/by-uuid/UUID-OF-/DEV/SDA2 /home btrfs compress=lzo,noatime,nodiratime,space_cache,ssd,discard,subvol=@home 0 2   
/dev/disk/by-uuid/UUID-OF-/DEV/SDA1 /boot/efi vfat umask=0077 0 1  

Step 5: update your bootloader

update-initramfs -u -k all
grub-install --recheck /dev/sda
update-grub

finish the install (setup the main user) and reboot.

Step 6: Install zram-config (Optionnal but recommanded)

reboot into your new system, open a terminal:

sudo apt-get install zram-config

reboot

Step 8: Enable RAID1 with BTRFS (Optionnal but recommanded)

reboot into your new system
plug another drive in your machine (optimally of the same size as /dev/sda).
let's assume you added /dev/sdb
you can partition sdb to have sdb1 or you can use the full disk sdb

btrfs device add -f /dev/sdb1 /
btrfs fi show /
btrfs balance start -v -mconvert=raid1 -dconvert=raid1 /
btrfs fi usage /

Step 9: do the upgrades

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo apt-get autoremove -y
sudo apt-get autoclean

Step 10: Setup ssh

setup ssh with pubkey authentication
setup fail2ban

Step 11: Setup IPtables

setup your firewall rules
be careful, docker use its own chain in iptable
https://fralef.me/docker-and-iptables.html

Step 12: Make your first snapshot

mount the whole btrfs:

sudo -i
mount -o compress=lzo,ssd,discard,space_cache,noatime,nodiratime /dev/sdb2 /mnt
cd /mnt
ls

snapshot:

mkdir snapshots
btrfs subvolume snapshot -r @ snapshots/$(date -Ins).@
btrfs subvolume snapshot -r @home snapshots/$(date -Ins).@home
btrfs subvolume list .

and to rollback:

cd /mnt
mv @ @.old
btrfs subvolume snapshot snapshots/DATE_OF_THE_SNAPSHOT.@ @

reboot and done (you can remove the @.old if not needed anymore)

btrfs subvolume delete /mnt/@.old

for subvolume that are not the rootfs, you can just unmount them, rollback and mount them again.

umount /home
mv /mnt/@home /mnt/@home.old
btrfs subvolume snapshot /mnt/snapshots/DAE_OF_THE_SNAPSHOT.@home /mnt/@home
mount -a

You can also use a bash script to help you deal with the snapshots scheduling and rolling:
https://ownyourbits.com/2017/12/27/schedule-btrfs-snapshots-with-btrfs-snp/
https://github.com/nachoparker/btrfs-snp/blob/master/btrfs-snp