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.


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

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  


/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  

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  


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

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  


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: