by 2000

Full disk encryption: BTRFSonLUKS with separate root, home and pkg subvolumes; hibernation with a swapfile; auto-snapshots with easy system rollback (GUI); boot into snapshots

This tutorial assumes EndeavourOS will be the only OS on the device.

What you’ll end up getting:

  • BTRFSonLUKS (fully LUKS encrypted single partition containing a btrfs filesystem with /boot, /‘root’ and /home)
  • /, /home, swapfile, pkg cache as separate subvolumes to allow easy and storage space saving of snapshots of the root system
  • automated creation of snapshots (on system upgrade & daily & boot)
  • ability to boot into a working snapshot from the grub menu (automated creation of boot entries) and then setting this or other snapshot as new default system (from GUI)
  • swapfile, with the ability to hibernate

Not everybody always has the time, knowledge and/or will to go through the process of chrooting, downgrading, and repairing if something breaks.
With this low-maintenance type of setup it should be possible to recover/rollback from a problematic upgrade by simply booting into a working snapshot (these snapshots are created automatically) and setting this as the new default from within the booted system. You could then just wait a couple of days and then check if the upgrade problems still persist. Most of the time the problem will be fixed upstream by then. Note that the creation or restore of a snapshot takes about a second!

The following is a tutorial on setting up this type of system with the help of calamares (the EOS installer) and a little cli.

Note: The provided cli commands can be copied and pasted/run in bulk, adding only a couple of minutes to your normal install time. If you really need to know what is actually happening, I have provided a step-by-step explanation of the used commands in the “BTRFSonLUKS – verbose version” of this tutorial.

Note: For a +++ non-encrypted version +++ of this setup follow the instructions provided in this forum post or see the bottom of this article.


#01 – Boot into Live-CD environment & set up partitions

With the help of GParted, assuming you have an empty disk

(a) for UEFI systems:

  • create a GPT partition table
  • create sda1 with 300 to 512MiB, format as fat32 and set boot & esp flag
  • leave rest unallocated
 300-512MiB             |      rest                   xGiB 
 flag: boot & esp       |      unallocated          
 format: fat32            |                           
 /dev/sda1                 |                           

(b) for BIOS (legacy boot) systems:

  • create a GPT partition table
  • create sda1 with 8MiB, leave unformatted and set bios_grub flag
  • leave rest unallocated
 8MiB                  |      rest                 xGiB
flag: bios_grub    |      unallocated          
unformatted        |                           
/dev/sda1            |                            

With other storage types, /dev/sda1 could also be called /dev/nvme0n1p1 for example; in this case just substitute sda1 with nvme0n1p1.

#02OPTIONAL – Change default btrfs calamares settings for fstab

Open a Terminal and type (or mark and copy the commands below with ctrl-c and paste in terminal with shift-ctrl-v | you can always copy&paste all the lines shown in one block at once)

sudo sed -i 's/compress=lzo/compress=zstd/' /usr/share/calamares/modules/fstab.conf
sudo sed -i 's/autodefrag/autodefrag,compress=zstd/' /usr/share/calamares/modules/fstab.conf

#03 – Install system with calamares (off- or online install)

Set up calamares like you usually would (Location, Keyboard, Users, …) but
choose Manual partioning and edit (double-click the partition(s) in the list view) to the specifications given below …

(a) for UEFI systems:

  1. /dev/sda1
  • Mount point -> /boot/efi
  • set boot flag
  • keep fat32
  1. free space
  • Mount point -> /
  • File system -> btrfs
  • Encrypt: choose a secure password

Let Calamares finish the installation. If you get a warning about missing esp or boot flag(s) on /dev/sda1 just add them with GParted and continue with the install.

(b) for BIOS (legacy boot) systems:

  1. free space
  • Mount point -> /
  • File system -> btrfs
  • Encrypt: choose a secure password

Let Calamares finish the installation. Ignore the window notice “Option to use GPT on BIOS”. We had that set up by gparted already. Continue with the install.

After the install finishes, do NOT check the “Restart now” checkbox.

#04 – Choose your swapfile size

Note: If you want to use hibernation, then you must add swap because the content of the RAM will be written to the swap file. This also means that the swap size should be at least the size of RAM. Read here about choosing swap sizes.

e. g. “8G” or “8192M”


#05 – Run the following

Just copy&paste all the lines in the terminal at once.

Note: Some of the commands below may report an error if you’re setting up a non uefi system. Just ignore any errors at this stage.

sudo mkdir /mnt/btrfs
btrfsonluks=`sudo blkid -o device | grep luks`
sudo mount -o subvolid=5 $btrfsonluks /mnt/btrfs
sudo sed -i 's/compress=zstd 0 1/compress=zstd 0 0/' /mnt/btrfs/@/etc/fstab
sudo sed -i 's/compress=zstd 0 2/compress=zstd 0 0/' /mnt/btrfs/@/etc/fstab
sudo btrfs subvolume create /mnt/btrfs/@var-cache-pacman-pkg
fstabstr=`grep "/home" /mnt/btrfs/@/etc/fstab`
sudo sh -c "echo $fstabstr >> /mnt/btrfs/@/etc/fstab"
sudo btrfs subvolume create /mnt/btrfs/@swap
sudo mkdir /mnt/btrfs/@/swap
sudo sh -c "printf '\n$btrfsonluks /swap          btrfs   subvol=@swap,defaults,compress=no 0 0\n' >> /mnt/btrfs/@/etc/fstab"
sudo truncate -s 0 /mnt/btrfs/@swap/swapfile
sudo chattr +C /mnt/btrfs/@swap/swapfile
sudo btrfs property set /mnt/btrfs/@swap/swapfile compression none
sudo fallocate -l $swapsize /mnt/btrfs/@swap/swapfile
sudo chmod 600 /mnt/btrfs/@swap/swapfile
sudo mkswap /mnt/btrfs/@swap/swapfile
sudo swapon /mnt/btrfs/@swap/swapfile
sudo sh -c "echo '/swap/swapfile none swap defaults 0 0' >> /mnt/btrfs/@/etc/fstab"
gcc -O2 -o btrfs_map_physical btrfs_map_physical.c
offset=`sudo ./btrfs_map_physical /mnt/btrfs/@swap/swapfile`
offset_arr=(`echo ${offset}`)
offset_pagesize=(`getconf PAGESIZE`)
offset=$(( offset_arr[25] / offset_pagesize ))
sudo sed -i "s/loglevel=3/loglevel=3 resume_offset=$offset/" /mnt/btrfs/@/etc/default/grub
sudo sed -i "s#loglevel=3#resume=$btrfsonluks loglevel=3#" /mnt/btrfs/@/etc/default/grub
sudo sed -i 's/keymap encrypt filesystems/keymap encrypt filesystems resume/' /mnt/btrfs/@/etc/mkinitcpio.conf
sudo mkdir /mnt/chroot
sudo mount -o compress=zstd,subvol=@ $btrfsonluks /mnt/chroot
efidevice=`sudo blkid -o device -l -t TYPE=vfat`
sudo mount $efidevice /mnt/chroot/boot/efi
sudo arch-chroot /mnt/chroot
sudo pacman --noconfirm -S cronie
sudo systemctl enable cronie.service
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo mkinitcpio -p linux

#06REBOOT into your new system

Run the following …

sudo pacman --noconfirm -Syy &&
yay --noconfirm -S timeshift timeshift-autosnap grub-btrfs

Then run …

sudo cp /etc/timeshift/default.json /etc/timeshift/timeshift.json &&
fs_uuid=`sudo blkid -o device | grep luks` &&
fs_uuid=`sudo blkid -o value -s UUID $fs_uuid` &&
sudo sed -i "s/backup_device_uuid\" : \"/backup_device_uuid\" : \"$fs_uuid/" /etc/timeshift/timeshift.json &&
fs_uuid=`sudo blkid -o device -l -t TYPE=crypto_LUKS` &&
fs_uuid=`sudo blkid -o value -s UUID $fs_uuid` &&
sudo sed -i "s/parent_device_uuid\" : \"/parent_device_uuid\" : \"$fs_uuid/" /etc/timeshift/timeshift.json &&
sudo sed -i 's/run" : "true/run" : "false/' /etc/timeshift/timeshift.json &&
sudo sed -i 's/btrfs_mode" : "false/btrfs_mode" : "true/' /etc/timeshift/timeshift.json &&
sudo sed -i 's/  "include_btrfs_home" : "false",/  "include_btrfs_home_for_backup" : "false",\n  "include_btrfs_home_for_restore" : "false",/' /etc/timeshift/timeshift.json &&
sudo sed -i 's/schedule_daily" : "false/schedule_daily" : "true/' /etc/timeshift/timeshift.json &&
sudo sed -i 's/schedule_boot" : "false/schedule_boot" : "true/' /etc/timeshift/timeshift.json &&
sudo sed -i 's/count_boot" : "5/count_boot" : "3/' /etc/timeshift/timeshift.json
sudo timeshift --create --comments "1st"

#07 – OPTIONAL – Limit the amount of maximum snapshots

Timeshift cleans the automatically created snapshots but the ones you create manually aren’t handled by Timeshift and would be kept indefinetily. Just choose a high number if you prefer to delete these manually and not let the system only keep the newest (e. g.) 15 snapshots.

Note that a large number of snapshots could cause system slowdowns.

Choose the amount of maximum snapshots your system will allow and keep.


Then execute …

sudo sh -c '
cat > /etc/systemd/system/limit-timeshift-snapshots-update-grub.service <<- "EOF"
Description=Keep only latest max_snapshots timeshift snapshots and update grub.cfg before shutdown


' &&
sudo sed -i "s#max_snapshots#$max_snapshots#" /etc/systemd/system/limit-timeshift-snapshots-update-grub.service &&
sudo sed -i "s#ExecStop=#ExecStop=/usr/bin/sh -c \"cd /run/timeshift/backup/timeshift-btrfs/snapshots/ \&\& rm -rf \`ls -1r | awk 'NR>$max_snapshots'\` \&\& /usr/bin/grub-mkconfig -o /boot/grub/grub.cfg\"#" /etc/systemd/system/limit-timeshift-snapshots-update-grub.service &&
sudo systemctl enable limit-timeshift-snapshots-update-grub.service &&
sudo systemctl start limit-timeshift-snapshots-update-grub.service

#08OPTIONAL – Create desktop shortcuts for Timeshift

If your Desktop Environment allows desktop shortcuts then running the following will create shortcuts to (1) “Timeshift” and a command to (2) generate a manual snapshot of root.

Note: to get rid of these later on just delete the shortcuts from your desktop

sh -c '
cat > ~/Desktop/timeshift-gtk.desktop <<- "EOF"
[Desktop Entry]
GenericName=System Restore Utility
Comment=System Restore Utility
chmod +x ~/Desktop/timeshift-gtk.desktop
sh -c '
cat > ~/Desktop/create_snapshot.desktop <<- "EOF"
[Desktop Entry]
Name=Create Snapshot
Comment=Create btrfs snapshot of root
sed -i "s#Exec=#Exec=sudo sh -c \'timeshift --create --comments \"manual\" \&\& sleep 2\'#" ~/Desktop/create_snapshot.desktop
chmod +x ~/Desktop/create_snapshot.desktop

DONE! You should now have a fully encrypted system with the ability to rollback to automatically (and manually) created snapshots and be able to hibernate.

Note that this setup isn’t meant to be a backup strategy replacement! The snapshots are stored on the same disk as your system; if this fails the snapshots won’t be accessible. At least your /home subvolume should be backuped to another physical device. So, just apply your normal backup strategy of choice.


#How to RESTORE a snapshot

A – If you ever need to reset your system to a stored state, just

  1. Launch Timeshift from the menu (or desktop shortcut)
  2. Select a snapshot and hit restore
  3. Reboot

That’s all. Takes mere seconds and doesn’t get any easier.
BTW, you could also restore a snapshot from the cli!

B – In case you can’t boot into your desktop environment try to

  1. Boot directly into a snapshot from the GRUB (boot) menu
  2. see A (above) …

C – In case you need to restore a snapshot from a live system (e. g. EndeavourOS Install medium)

  1. Boot into the live environment
  2. Install Timeshift into the live environment by executing
sudo pacman --noconfirm -Syy cronie
yay --noconfirm -S timeshift
  1. see A (above) …

D – In case you need to chroot from a live system (e. g. EndeavourOS Install medium)

  1. Boot into the live environment
  2. Decrypt and mount your luks partition (e. g. /dev/sda2)
sudo cryptsetup luksOpen /dev/sda2 crypt &&
sudo mount -o compress=zstd,subvol=@ /dev/mapper/crypt /mnt
  1. Only on UEFI systems: Mount your EFI boot folder (e. g. /dev/sda1)
sudo mount /dev/sda1 /mnt/boot/efi
  1. chroot into your system
sudo arch-chroot /mnt
  1. Do some root stuff …


+++ non-encrypted version +++

For a “non-encrypted version” of this setup follow the instructions provided above, but …

Don’t choose encrypt.


  • change
btrfsonluks=`sudo blkid -o device | grep luks`




  • change
fs_uuid=`sudo blkid -o device | grep luks` &&


fs_uuid=`sudo blkid -o device | grep sda2` &&
  • delete (do not run) …
fs_uuid=`sudo blkid -o device -l -t TYPE=crypto_LUKS` &&
fs_uuid=`sudo blkid -o value -s UUID $fs_uuid` &&
sudo sed -i "s/parent_device_uuid\" : \"/parent_device_uuid\" : \"$fs_uuid/" /etc/timeshift/timeshift.json &&

You should now have an equivalent system to the guide, without the benefit of full disk encryption.


Initially posted on the forum: 2020-03-03
Wiki version: 2020-07-27
2020-09-29 – changed some wording; added info on non-encrypted version
2020-11-29 – addressed timeshift/xapp build bug; undid these changes after an upstream fix; addressed timeshift config location change

Connect with us:

BTRFSonLUKS – quick copy & paste version

  • by