Manual Disk Encryption Setup in Lubuntu 18.04 Installer

This guide describes how I set up disk encryption and LVM manually while installing Lubuntu Desktop 18.04. Since the installer doesn’t support manipulation of LVM partitions in the GUI, this guide gives step-by-step instructions for setting up LUKS and LVM in the command line.

While I wrote this while installing Lubuntu, this guide should also work with regular Ubuntu and the other Ubuntu variants.

To begin, boot the Lubuntu installer and select “Try without installing”. Don’t launch the installer program yet, as we will need to set up our disk encryption and LVM in the terminal first.

Step 1: partitioning

The first step is to create the GPT partitions on the disk. For this post we’ll use /dev/sda as the device name. Make sure to change this to the device that you are installing Lubuntu on.

I chose to use an unencrypted /boot partition for simplicity. If you also need /boot to be encypted, this will be a more complex process, but there are other guides on full-disk encryption that may help.

This step can be done easily with a GUI: I used gparted, for example. If there isn’t one already, create an EFI system partition (see this Arch Linux wiki page for more details). As mentioned above, I also created a plain ext4 partition for /boot. Finally, I wanted to encrypt the rest of my disk, so I created one last partition, spanning the rest of the disk, with no filesystem (we’ll format this partition for encryption in the next step).

If using gparted, click “Apply all operations” (the checkmark in the toolbar, or under the Edit menu) to write the partition table. You should now be able to run lsblk to see these changes.

At the end of this step, my setup looks like this:

sda
|-sda1  480M  /boot/efi
|-sda2  1G    /boot
|-sda3  <rest>

Step 2: setup dm-crypt

In this step, we will encrypt the partition sda3 and set it up as a LVM physical volume. First, setup LUKS, which is the disk encryption format that Ubuntu uses:

cryptsetup luksFormat --type=luks1 /dev/sda3

Note that I chose the luks1 format, but there is also a newer luks2. StackOverflow has a discussion on the trade-offs between the two.

Once the partition is formatted for LUKS, we can now “open” (i.e. create a mapping) the device so that we can setup LVM. The data stored on disk is encrypted, but by mapping the device, we create a virtual, decrypted version of the partition that we can manipulate. This allows us to easily layer on LVM, or even plain filesystems, while keeping the underlying physical storage encrypted. Open (“decrypt”) the device as follows:

cryptsetup open /dev/sda3 sda3_crypt

Note that sda3_crypt is an arbitrary name for the mapped device, which will be available at /dev/mapper/sda3_crypt. You can select whatever name you want as long as you use the same name in the steps below.

Step 3: setup LVM

In this step, we will setup LVM on the encrypted device. LVM allows us to take one physical volume (i.e. our encrypted volume) and partition it flexibly into multiple logical volumes. Unlike a physical disk, these logical volumes can be manipulated much more easily after they are created, including resizing, moving, and creating new volumes.

There are three main concepts in LVM: physical volume (PV), volume group (VG), and logical volume (LV). A logical volume is the equivalent of a traditional partition: after creating a logical volume, you can format it as ext4 and mount it, for example. A volume group groups together several logical volumes, and you can think of it as the equivalent of a traditional physical disk. Finally, a physical volume (PV) represents the underlying storage for a volume group. Usually, this is a physical disk partition, or in our case, a LUKS device.

We’ll set up one PV (the mapped LUKS device) and one VG, and put our partitions inside that one VG. First the PV:

pvcreate /dev/mapper/sda3_crypt

Now we’ll create a VG on top of this PV. Note that lubuntu-vg is an arbitrary name:

vgcreate lubuntu-vg /dev/mapper/sda3_crypt

Finally, we can create our logical volumes inside this VG. You can customize this step to your needs, but in this example we’ll create two partitions for swap and root:

lvcreate -L 8G --name lubuntu-vg
# 100%FREE uses the rest of the VG
lvcreate -l 100%FREE --name root lubuntu-vg

There is no need to format these partitions, as we’ll use the Lubuntu installer to do that next.

This section illustrated only a very basic use of LVM, but LVM has many more advanced features and use cases that weren’t covered here. This StackOverflow post has some pointers to more resources if you’re interested in diving deeper.

Step 4: install Lubuntu

Once the LVM setup is done, we can perform the Lubuntu installation. Simply open the installer, and select “Something else” when prompted about the disk. You should see the LVM volumes you created here. Select them and pick the mount point as usual. Make sure that you select the LVM volumes rather than the underlying crypt device (sda3_crypt) or physical partition (sda3).

Finish the installation, but do not reboot the system yet.

Step 5: tweaks to boot encrypted root partition

Before rebooting into your new system, we must perform some final steps to ensure that the new system will boot properly. If this is not done, it’s possible that you’ll be dropped into an “initramfs” recovery prompt.

  1. Initrd must contain the required software to decrypt/map the encrypted partition.
  2. Initrd must know which partition to decrypt.

Because these steps need to be performed in the newly installed (target) system, and we are still in the Lubuntu live USB environment, we need to chroot into the target.

Mount the target and chroot

The target’s root filesystem should already be mounted at /target, but if not, do that before continuing. Also, make sure that special filesystems are mounted in the target root before chrooting, in particular:

mount -o bind /dev /target/dev
mount -t proc proc /target/proc
mount -t sysfs sysfs /target/sys
mount -o bind /run /target/run

If you are using a separate /boot partition like me, make sure that is mounted as well, since we will be updating the initrd images (make sure to replace /dev/sda2 with your boot partition):

mount /dev/sda2 /target/boot

Now we are ready to chroot into the target:

chroot /target /bin/bash

Now we are operating in the context of the target, installed system.

Include cryptsetup modules in initrd

The first tweak we should make is to include the cryptsetup modules in the initrd. Open the file /etc/cryptsetup-initramfs/conf-hook and make sure that CRYPTSETUP=y. See this StackOverflow post for more details.

Add partition to crypttab

Next, we need to indicate which partition to be decrypted on boot. There are at least two ways to do this: a cryptopts boot kernel parameter, and crypttab. I picked the crypttab method, which involves adding a line like the following to /etc/crypttab:

sda3_crypt UUID=<uuid> none luks,discard

Replace <uuid> with the UUID of your encrypted partition. You can find this out by running blkid as root, which will print out something like:

/dev/sda3: UUID="12345678-abcd-abcd-abcd-1234567890ab" TYPE="crypto_LUKS" PARTUUID=...

Paste the UUID displayed into /etc/crypttab. For the example above, that would be:

sda3_crypt UUID=12345678-abcd-abcd-abcd-1234567890ab none luks,discard

The final option discard is optional, and presents a trade-off between SSD performance and security. Adding discard enables TRIM which can potentially enable higher performance on SSDs, by allowing the SSD to reclaim freed blocks in the background. However, this comes with a security trade-off in the form of potentially leaking some metadata. Personally, I chose to enable discard because the type of metadata that may be leaked (the filesystem that’s being used is given as an example) is not important to my use case. See this page on the Arch Linux wiki for more details.

If you prefer the cryptopts method, this post contains an example. This line should be added to the kernel boot options in /etc/default/grub (don’t forget to update GRUB afterwards).

Rebuild the initrd image

After making the two above tweaks, rebuild the initrd image:

update-initramfs -u -k all

To ensure that the changes were applied successfully without rebooting, you can inspect the generated image with unmkinitramfs. For example, this will extract the contents of the image to /tmp/initrd:

mkdir /tmp/initrd
unmkinitramfs /boot/initrd.img-5.3.0-53-generic /tmp/initrd

These files should be present:

ls -l /tmp/initrd/main/sbin/cryptsetup
ls -l /tmp/initrd/main/conf/conf.d/cryptroot

Check that the cryptroot file contains the same UUID that you added to crypttab above. If the initrd looks good, then it’s time to reboot and try booting into your new encrypted Lubuntu system!

Other resources

https://medium.com/@chrishantha/encrypting-disks-on-ubuntu-19-04-b50bfc65182a https://github.com/jjakob/wiki/wiki/Migrating-an-unencrypted-PureOS-Debian-install-to-fully-encrypted