Create a GPT partition table with gdisk that automatically takes care of 4k disks:

gdisk /dev/sdX

press "n" for "new partition" and choose the defaults for following questions to create a partition that uses the whole disk. Afterwards, write the changes with "w" to the disk.

Create an encrypted LUKS container, ArchWiki suggests to use aes-xts-plain64 instead of aes-xts-plain for disks >2TB:

cryptsetup -c aes-xts-plain64 -s 512 luksFormat /dev/sdX1

"-s 512" sets the encryption to AES-256 (no typo). Afterwards open the container with:

cryptsetup luksOpen /dev/sdX1 mycontainer

This creates a file /dev/mapper/mycontainer that we use as new target to create the Btrfs filesystem:

mkfs.btrfs -L mylabel /dev/mapper/mycontainer

Now mount the new filesystem:

mount /dev/mapper/mycontainer /mnt/mycontainer/


Different guides suggest to immediately create a subvolume as it eases further operations, e.g. rollbacks:

btrfs subvolume create /mnt/mycontainer/main

Afterwards, we set this subvolume as default:

btrfs subvolume set-default main /mnt/mycontainer/main

Unmount and remount the new default volume:

umount /mnt/mycontainer/
mount /dev/mapper/mycontainer /mnt/mycontainer/

If you want to mount the root volume later, use:

mount /dev/mapper/mycontainer /mnt/mycontainer/ -o subvol=/


If you decide that redundancy would be good afterwards, you first add a second device:

btrfs device add /dev/sdY1 /mnt/mycontainer/

and to truly mirror the data, you have to start a balance run with:

btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt/mycontainer

The progress of this operation can be checked with:

btrfs balance status /mnt/mycontainer/