Skip to content

Instantly share code, notes, and snippets.

@ispanos
Last active October 22, 2023 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ispanos/40cdef90db2f596f679a1a2b6d0177c4 to your computer and use it in GitHub Desktop.
Save ispanos/40cdef90db2f596f679a1a2b6d0177c4 to your computer and use it in GitHub Desktop.
Notes on how I set up Btrfs on Luks for storing data.

BTRFS on LUKS for drives containing data

Reading material

Frequently Asked Questions on Cryptsetup/LUKS

Getting started with btrfs

Wipe the drive

If the device is new or you've never stored any sensitive data on it, you could skip the dd commands.

wipefs -a <device>
dd if=/dev/zero of=<device> status=progress
dd if=/dev/urandom of=<device> status=progress

Install dependencies

sudo apt install btrfs-progs cryptsetup

Create LUKS volume

Before running the luksFormat command, run cryptsetup --help to make sure that the compiled-in defaults set by your distribution are what you want them to be. In my case the defaults are:

Default compiled-in metadata format is LUKS2 (for luksFormat action).

Default compiled-in key and passphrase parameters:
	Maximum keyfile size: 8192kB, Maximum interactive passphrase length 512 (characters)
Default PBKDF for LUKS1: pbkdf2, iteration time: 2000 (ms)
Default PBKDF for LUKS2: argon2i
	Iteration time: 2000, Memory required: 1048576kB, Parallel threads: 4

Default compiled-in device cipher parameters:
	loop-AES: aes, Key 256 bits
	plain: aes-cbc-essiv:sha256, Key: 256 bits, Password hashing: ripemd160
	LUKS: aes-xts-plain64, Key: 256 bits, LUKS header hashing: sha256, RNG: /dev/urandom
	LUKS: Default keysize with XTS mode (two internal keys) will be doubled.
cryptsetup luksFormat --label=bd0 <device>
cryptsetup isLuks <device> && echo Success
cryptsetup luksOpen <device> bd0
cryptsetup luksDump <device>

I like partitions and filesystems to have a label. If you forgot to set a label you can use.

sudo cryptsetup config /dev/sdb1 --label YOURLABEL

Throughout the rest of the notes bd0 will be the name of the mapped device in /dev/mapper/. Feel free to replace it with any name you want.

Create a btrfs subvolume for data

Format drive with btrfs.

mkfs.btrfs --label bd0 -f /dev/mapper/bd0

Scan for btrfs filesystems to verify.

btrfs -v device scan -d

Mount the whole filesystem and create the subvolume.

mkdir /mnt/btrfs
mount -t btrfs /dev/mapper/bd0 /mnt/btrfs
btrfs subvolume create /mnt/btrfs/bd0data

Verify that the subvolume is created. And note the subvolume id. For one of my devices the first subvolume was 257, for the other one it was 256.

btrfs subvolume list -ap /mnt/btrfs

Unmount the btrfs filesystem to mount the subvolume.

umount /mnt/btrfs

Mount the subvolume using its id (Btrfs mount options).

mkdir -p /mnt/bd0
mount -o subvolid=257,compress-force=zstd /dev/mapper/bd0 /mnt/bd0

Compression is awesome, use it.

empirical testing on multiple mixed-use systems showed a significant improvement of about 10% disk compression from using compress-force=zstd over just compress=zstd, which also had 10% disk compression.

Set compression property, after mounting the drive, but before adding any data. This should be permanent

btrfs property set /mnt/bd0 compression zstd

Set default subvolume.

btrfs subvolume set-default 257 /mnt/bd0

Reboot and try to access the data.

lsblk
cryptsetup luksOpen /dev/sdb bd0
sudo mount -o subvolid=257,compress-force=zstd /dev/mapper/bd0 /mnt/bd0

Unmount the drive

umount /mnt/bd0
cryptsetup luksClose /dev/mapper/bd0

Auto-mounting note.

Just use the gnome disks gui. Make sure to edit the default mount options to include compression.

Additional notes

systemd unit to mount btrfs volume

In Pop-os, udisks2.service auto-mounts drives in /media/$USER/<drivelabel> once you open the "Other Locations" in Nautilus.

For udisks2 config files ls /etc/udisks2/

systemctl status udisks2.service
...
Jan 14 22:30:40 udisksd[1344]: Unlocked device /dev/sdb as /dev/dm-3
Jan 14 22:30:41 udisksd[1344]: Mounted /dev/dm-3 at /media/yiannis/bd0 on behalf of uid 1000

A udev rule for udisks2 can change the default path for mounting the drives. The following is a udev rule for removable media from the Archwiki.

udiskie

udisks2 automounter with optional notifications, tray icon and support for password protected LUKS devices. See the udiskie wiki for details. This Polkit configuration might be needed for window-managers.

Compressing all items after the fact

I did this and trust me, you don't want to compress the files after the fact. Unless you are not sure if compression would be of benefit on your data. It took me around 3 hours to run the following command for 1 TB of data on an HDD.

btrfs property set /mnt/bd0 compression zstd
btrfs filesystem defrag -r -c zstd /mnt/bd0 # the "-c zstd" part isn't 100% tested

Backup

Please read the official Backup and Data Recovery section in the FaQ.

ATTENTION: If you are going to read just one thing, make it the section on Backup and Data Recovery.

For the sake of convenience, I'm adding the command to back up you LUKs header.

cryptsetup luksHeaderBackup <device> --header-backup-file <file> 

In my test the <device> was /dev/sdb.

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