LUKS, LVM and Linux Boot
LUKS encrypts your hard drive, while LVM allows to have partitions on your hard drive which are easier to manage and resize than with MBR/GPT. We won’t discuss MBR/GPT since LVM is better. From the point of view of Linux, hard disk is a block device; MBR/GPT/LVM allows you to have multiple block devices stored on one block device, while LUKS creates a block device which encrypts/decrypts data and stores it on an underlying block device.
It’s common to have:
- A hard disk partitioned via GPT. Note that every partition is a block device.
- A LUKS, encrypting contents of one block device
- LVM which allows you to have multiple block device on your LUKS-encrypted block device. See the Basic Guide to Encrypting Linux Partitions With LUKS for more details.
Overview of partitioning schemes:
- MBR (Master Boot Record) - an old way to “partition” your hard-drive: divide a block device into multiple block devices.
No longer used. Use
fdisk
orgparted
to resize and move partitions. Note that resizing/moving partitions involves physically copying data around. - GPT (GUID Partition Table) - an upgrade over MBR; this is what you most probably use. Use
fdisk
orgparted
to resize and move partitions. Note that resizing/moving partitions involves physically copying data around. See Difference between GPT and MBR for more details. - LVM - an upgrade over MPR+GPT, allows resizing/moving partitions without the need of physically copying data around; supports all sorts of RAIDs which we won’t discuss here. See the Complete Beginner’s Guide to LVM in Linux for more details.
Note that GPT is preferred on physical devices over LVM, simply because booting from LVM disk is very tricky. Therefore, use GPT for disks you boot from, use LVM for everything else.
Analysing the current setup
Use the following commands to analyze your current setup:
sudo dmsetup ls --tree -o blkdevname
prints a tree of how block devices are nestedsudo lsblk -o name,size,fstype
same as above but better: also prints sizes and filesystems:
NAME SIZE FSTYPE
loop0 4K
loop1 44.4M
...
sda 1.7T
├─sda1 1M
├─sda2 1G ext4
└─sda3 1.7T crypto_LUKS
└─dm_crypt-0 1.7T LVM2_member
├─vg0-lv0--swap 4G swap
└─vg0-lv1--root 1.7T ext4
You can find the devices here:
/dev/sda
,/dev/sda1
,/dev/sda2
,/dev/sda3
/dev/mapper/dm_crypt-0
which usually symlinks to/dev/dm-0
/dev/vg0/lv0-swap
which symlinks to/dev/dm-1
Analysing LUKS
> sudo cryptsetup status /dev/mapper/dm_crypt-0
/dev/mapper/dm_crypt-0 is active and is in use.
type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/sda3
sector size: 512
offset: 32768 sectors
size: 3748612096 sectors
mode: read/write
flags: discards
Analysing LVM
We won’t be using RAID capabilities of LVM, so in this case, physical volume is “the same thing” as volume group. in other words, we’ll have one volume group on a physical volume, which is stored on one block device. Use:
pvscan
,pvs
andpvdisplay
to learn about physical volumesvgscan
,vgs
andvgdisplay
to learn about volume groupslvscan
,lvs
andlvdisplay
to learn about logical volumes
discard
Make sure discard is enabled for both LUKS and LVM when running on a SSD.
Creating
I’ll experiment on a Linux running in a VM, but you can experiment on an actual machine as well - just plug in USB stick or a new hard drive, or create a partition on your existing hard drive.
First, let’s create the GPT partition on your new disk, say it’s /dev/vdb
.
Just follow the Partition+Format Storage Tutorial,
or use parted
/gparted
. First, make sure with parted
and lsblk
that the device is indeed /dev/vdb
.
Then:
$ sudo parted /dev/vdb mklabel gpt
$ sudo parted -a opt /dev/vdb mkpart primary 0% 100%
$ sudo parted -l
The partition should now be ready, and a new block device should be available: /dev/vdb1
.
Note: Actually you don’t have to partition the disk and you can create LUKS directly on
/dev/vdb
. You can skip the steps above if you’d like, then use/dev/vdb
instead of/dev/vdb1
in steps below.
Now we’ll use LUKS to create an encrypted block device on top of /dev/vdb1
:
$ sudo cryptsetup luksFormat /dev/vdb1
$ sudo cryptsetup open /dev/vdb1 dmcrypt0
$ sudo cryptsetup status /dev/mapper/dmcrypt0
We have a block device that encrypts its contents automatically. However,
the device won’t be opened automatically upon boot, you need the /etc/crypttab
file;
see below.
We can now configure LVM on top of LUKS. In theory we could also use GPT, but it’s far more common to use LVM:
$ sudo pvcreate /dev/mapper/dmcrypt0
$ sudo pvdisplay
$ sudo vgcreate vg0 /dev/mapper/dmcrypt0
$ sudo vgdisplay
We’ll create two logical volumes: one for swap, other for a btrfs filesystem.
$ sudo lvcreate -L 1GB -n vg0-lv0-swap vg0
$ sudo lvcreate -l 100%FREE -n vg0-lv1-btrfs vg0
$ sudo lvdisplay
To create the final filesystems, run:
$ sudo mkswap /dev/vg0/vg0-lv0-swap
$ sudo swapon /dev/vg0/vg0-lv0-swap
$ free -h
$ sudo mkfs.btrfs /dev/vg0/vg0-lv1-btrfs
$ sudo mkdir -p /mnt/mydisk
$ sudo mount /dev/vg0/vg0-lv1-btrfs /mnt/mydisk
$ sudo lsblk -o name,size,fstype
Done - now we have an encrypted swap and an encrypted disk mounted at /mnt/mydisk
.
However, those things won’t activate automatically upon reboot - for that we need
to enable auto-mounting.
Auto-mounting
In order for the LUKS block device to open automatically during the boot, you need to mention
it in the /etc/crypttab
file:
dmcrypt0 /dev/vdb1 none luks,discard
Reboot - Ubuntu will now ask for password to unlock the encrypted device upon boot. See crypttab man pages for more details.
In order to auto-activate swap and the encrypted btrfs filesystem, we need to add those to
/etc/fstab
:
/dev/vg0/vg0-lv0-swap none swap sw 0 0
/dev/vg0/vg0-lv1-btrfs /mnt/mydisk btrfs defaults 0 1
Done. Now, if you reboot, Linux will ask for the LUKS password on boot, then it will auto-activate swap and auto-mount the btrfs filesystem. Reboot, enter the password and verify that all works:
$ sudo lsblk -o name,size,fstype
vdb 10G
vdb1 10G crypto_LUKS
dmcrypt0 10G LVM2_member
vg0-vg0--lv0--swap 1G swap
vg0-vg0--lv1--btrfs 9G btrfs