Full Disk Encryption on Ubuntu with Manual Partitioning

For years the Ubuntu installer has supported full-disk encryption but the installer has suffered from not properly handling full-disk encryption in combination with manual partitioning. Such a setup is useful, for example, in a dual boot environment with both a Windows and an Ubuntu install, or with multiple Ubuntu partitions. Even though the installer doesn’t support it well, it is possible to do full-disk encryption (well, really, “full-partition” encryption) with a custom partition setup with a small amount of extra manual work. Here is how.

Note: I developed this using the Kubuntu 20.04 installer but the same procedure will work with the regular Ubuntu 20.04 or other variants.

Create Partitions

Boot into the live environment from the install medium. I used a Kubuntu 20.04 USB disk and selected the “Try Kubuntu” option to get to a live environment.

Open a Terminal and run sudo -i to get a root prompt. We’ll be using the gdisk utility to create partitions. (If you use an old MBR-style partitioned disk instead of GPT, you can use fdisk instead).

The main partitions we’ll need to add will be a boot and a system partition. The boot partition will not be encrypted in this scenario but the full system partition will be. This type of a setup does not necessarily protect from a targeted attack of someone inserting malicious code into the boot chain. But it does protect against someone stealing your laptop and also having access to proprietary company data or other private data, for example.

If you are starting from scratch with an empty disk and booting with UEFI, you’ll need to create an EFI system partition. I will assume this is in place already.

You can run lsblk to see your block devices. For me the disk I’m installing to is /dev/nvme0n1. Run gdisk /dev/nvme0n1 to open gdisk for this disk.

You can use d to delete any partitions first if necessary.

To create the boot partition, type n, select partition number, first sector, and enter +1G for the last sector to make the boot partition 1GB. Hit enter for hex code to use the default.

To create the system partition, type n again. I just hit enter to use the defaults for partition number, first sector, last sector, and hex code since I wanted to use the remainder of the disk for my encrypted Kubuntu installation.

Use the p command if desired to double-check the partitions and if you are ready to write them to disk then use the w command.

Run lsblk to see the updated partitions. Now we will format and create the encrypted partition, which will ease the installer into doing what we want.

For me my boot partition was /dev/nvme0n1p1 and my system partition was /dev/nvme0n1p2. Replace those names in the commands below with the correct partitions for your setup.

Run mkfs.ext4 /dev/nvme0n1p1 to format the boot partition.

Run cryptsetup luksFormat /dev/nvme0n1p2 to create an encrypted LUKS partition in the system partition. Enter YES to confirm and type enter your desired passphrase.

Run cryptsetup open /dev/nvme0n1p2 crypt_sys to open the encrypted partition.

Run mkfs.ext4 /dev/mapper/crypt_sys to create the root file system.

Install System

Run the installer. When you get to the Installation type screen to select your partition method, select Manual.

Select the /dev/nvme0n1p1 boot partition, set the type to ext4 and mount point to /boot.

Select the /dev/mapper/crypt_sys root file system device, set the type to ext4 and mount point to /.

Continue with the installation, but when the Installation Complete pop-up at the end pops up, do not select anything yet.

Make System Bootable

The Ubuntu installer has installed the new system to the encrypted partition, but has not configured the system to actually be able to boot from an encrypted partition. If you left the pop-up open at the end of the installation, then the installer will have left the new target system mounted at /target. You can see what file systems are mounted to /target with the command mount -l | grep /target.

Run the following commands to “chroot” into the target system:

mount -o bind /sys /target/sys
mount -o bind /proc /target/proc
mount -o bind /dev /target/dev
cp /etc/resolv.conf /target/etc
chroot /target /bin/bash

You now have a prompt within the context of the new target system. We need to create the /etc/crypttab file to allow the kernel to be able to locate the encrypted root file system.

Run blkid /dev/nvme0n1p2 to see the UUID of the encrypted partition. Copy the UUID, not including the doublequote characters.

Next run echo "crypt_sys UUID=copied_uuid none luks" >> /etc/crypttab (replacing “copied_uuid” with the copied UUID) to create /etc/crypttab.

Ok, now we need to update our “initial ramdisk file system” (initrd) in the /boot partition.

Run update-initramfs -u -k all.

You can now run exit to leave the chroot target environment and select Restart Now to reboot into the new system.

Troubleshooting

If the system does not boot or you miss a step and need to recover, you can boot into the live environment from an installation medium and attempt recovery without needing to go through the installation again.

From a terminal, run these commands to open the encrypted block device and mount the system to /target:

cryptsetup open /dev/nvme0n1p2 crypt_sys
mkdir /target
mount /dev/mapper/crypt_sys /target
mount /dev/nvme0n1p1 /target/boot
# If you have an EFI system partition, mount it as well:
#mount /dev/nvme0n1pX /target/boot/efi

This will recreate the state that the system was in when the installer was finished, and you can repeat any of the above commands necessary.

Comments are closed.