Setting Up a Swap File on BTRFS

With the release of btrfs-progs 6.1 (available in Debian Bookworm), you can create a swap file using the btrfs utility. It will take care of both preallocating the file and marking it as NODATACOW. As BTRFS can’t snapshot a subvolume that contains an active swap file, we will create a new subvolume for the swap file to reside in.

$ sudo btrfs subvolume create /swap
$ sudo btrfs filesystem mkswapfile --size 4g /swap/swapfile
$ sudo swapon /swap/swapfile

To auto-activate the swap file at boot, add the following line to /etc/fstab:

/swap/swapfile none swap defaults 0 0

Encrypted swap file

My entire root filesystem is encrypted, but having unencrypted swap can still lead to sensitive data being inadvertently exposed. The solution is to encrypt the swap file using random keys at boot. Add the following line to /etc/crypttab:

swap /swap/swapfile  /dev/urandom swap,cipher=aes-xts-plain64

And change the swap file location in /etc/fstab to point to /dev/mapper/swap like this:

/dev/mapper/swap none swap defaults 0 0

The new swap file will automatically start upon boot. To start it immediately, run:

$ sudo systemctl daemon-reload
$ sudo systemctl start systemd-cryptsetup@swap.service
$ sudo swapon /dev/mapper/swap

PSI-Notify

Adding a small amount of swap can significantly help in preventing the system from running out of memory. psi-notify can alert you when your running low on memory.

$ sudo apt install psi-notify
$ systemctl --user start psi-notify

Add the following line to ~/.config/psi-notify:

threshold memory some avg10 2.00

You may need to adjust the threshold to ensure it triggers at the right time for your needs. To test memory pressure, you can use the following command:

$ </dev/zero head -c 20G | tail

Short cryptsetup/LUKS tutorial

This short tutorial will guide you in encrypting a drive with cryptsetup and LUKS scheme.

Before starting, if the device had previous data on it, it’s best to delete any filesystem signatures that may be on it. Assuming that the drive we operate is /dev/sda you can use the following command to remove the signatures:

$ sudo wipefs --all /dev/sda --no-act

Remove the --no-act flag to actually modify the disk.

The next step is to actually format the drive using LUKS. This is done using the cryptsetup utility.

$ sudo cryptsetup luksFormat --type=luks2 /dev/sda

WARNING!
========
This will overwrite data on /dev/sda irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda: 
Verify passphrase: 

The command will prompt you to enter a passphrase for the encryption and should take a few seconds to complete.

The next step is to add an appropriate entry to crypttab which will simplify starting the dm-crypt mapping later. Add the following line to /etc/crypttab:

archive_crypt UUID=114d42e5-6aeb-4af0-8758-b4cc79dd1ba0 none luks,discard,noauto

where the UUID is obtained through lsblk /dev/sda -o UUID or a similar command. The archive_crypt is the name for the mapped device. It will appear as /dev/mapper/archive_crypt when the device is mapped. The none parameter specifies that no keyfile is used and the system should prompt for an encryption passphrase instead. The noauto, means not to attempt to load the device automatically upon boot. discard should be used if the underlying device is an SSD.

You can test everything works so far by opening and loading the LUKS device:

$ sudo cryptdisks_start archive_crypt

While the device is now encrypted, there is a possible leakage of metadata such as used blocks as an attacker can discern used vs unused blocks by examining the physical drive. This and other side-channel leaks can be mitigated by simply wiping the contents of the encrypted device.

$ openssl rand -hex 32 | openssl enc -chacha20 -in /dev/zero -pass stdin -nosalt | sudo dd if=/dev/stdin of=/dev/mapper/sda_crypt bs=4096 status=progress

We could also have used /dev/urandom but the above technique is much faster.

Now we can create the actual filesystem.

$ sudo mkfs.btrfs --label archive /dev/mapper/archive_crypt

At this point we’re actually pretty much done. You can add and entry to /etc/fstab to easily mount the filesystem and you’re done.

/dev/mapper/archive_crypt /home/guyru/archive btrfs noauto,user 0 0