Skip to Content

Full disk encryption (including /boot) on Ubuntu

Posted on

Torii Gates

Goal: Install Ubuntu Linux 18.04 LTS on a single encrypted partition using LVM on LUKS.

Devices that go out and about such as laptops and backup external drives should have their contents encrypted to guard against loss or theft. Plus you really want to encrypt everything (not just /home). All sorts of information and crypto weaknesses can seep into logfiles, temp files and swap memory. Tutorials and Linux distro installers that support encrypting root and home and swap will usually advise or auto-create a separate unencrypted boot partition; reasoning that the Linux kernel first needs to be found by the boot loader before it can proceed to decrypt the rest of the system. I certainly thought this was true and partitioned my Linux installs accordingly.

However, turns out that GRUB2 has for years supported booting from an encrypted boot directory courtesy of its cryptodisk module. Ubuntu (and Debian) installers do not provide the option of full disk encryption. But it is possible!

Let’s go!

Sample device uses BIOS MBR and boots in legacy boot mode. Below is a visual walk-through installing a minimal, console-only Ubuntu (or choose to add one of the supported desktops: Gnome, MATE, KDE, LXDE, etc.) that makes use of the entire disk as a single Linux Unified Key Setup (LUKS) encrypted partition that is used by the Logical Volume Manager (LVM) to create “virtual partitions” (Logical Volumes or LVs) of root and home. Installing LVM on top of the encrypted partition allows:

  • creation of multiple LVs protected by a single passphrase
  • dynamic resizing of LVs as needed
  • snapshots of LVs that can be used as backups or to restore a previous state

0. Prepare USB install media

Download the latest 18.04 “Bionic Beaver” 64-bit minimal alternate installer labelled mini.iso (or 32-bit version for older machines) and verify the image …

$ wget -c http://archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/mini.iso
$ wget -c http://archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/current/images/SHA256SUMS
$ sha256sum mini.iso && grep mini.iso SHA256SUMS
bed8a55ae2a657f8349fe3271097cff3a5b8c3d1048cf258568f1601976fa30d  mini.iso
bed8a55ae2a657f8349fe3271097cff3a5b8c3d1048cf258568f1601976fa30d  ./netboot/mini.iso

Write the installer to an unmounted USB stick using command dd. BE VERY CAREFUL TO NOTE THE PROPER DEVICE. ALL DATA ON THE DEVICE WILL BE OVERWRITTEN.

Example: If a USB stick appears as sde1, then write the installer to ‘sde’ (omit the partition number) using …

$ sudo dd bs=4M if=mini.iso of=/dev/sde && sudo sync

Minimal installer (requires network connection) will download all the latest packages during setup.

1. Launch

Install

Select language

Select location

Configure keyboard

Country of keyboard

English (US) is the default Qwerty layout. I use the Colemak keyboard layout …

Keyboard layout

Hostname

Archive country

Archive mirror

Proxy

At this stage, the contents of the installer are now loaded into memory and the USB stick can safely be removed.

Full name

Username

Passphrase

Verify passphrase

Clock

2. Partitions

On devices with > 128G of storage I separate the root and home directories. In this sample layout, storage will be configured with:

  • a single partition - sda1 - that uses the entire drive encrypted with LUKS
  • LVM is installed on the encrypted partition
  • LVM contains volume group labelled vg with a 24G root LV and a home LV that uses the remaining space

Partition method

Partition disk

Partition table

Free space

New partition

Partition size

Partition type

Use as

Howto use

Partition options …

Use as: physical volume for encryption
[...]
Erase data: no

If the hard disk has not been securely wiped prior to installing Ubuntu you optionally may configure Erase data: yes. Note, however, depending on the size of the disk this operation can last several hours.

Setup done

Configure encrypt

Write changes

Create encrypt

Device encrypt

Finish

Passphrase-031

Verify passphrase-032

Select partition

Use as-034

Howto use-035

Setup done-036

Configure lvm

Write changes-038

Create vg

Name vg

Device vg

Create lv

Select vg

Name lv

Size lv

Create lv-046

Select vg-047

Name lv-048

Size lv-049

Finish-050

Select lv-051

Use as-052

Howto use-053

Mount point-054

Select mount-055

Reserved blocks can be used by privileged system processes to write to disk - useful if a full filesystem blocks users from writing - and reduce disk fragmentation. On large, non-root partitions extra space can be gained by reducing the 5% default reserve set by Ubuntu to 1% …

Reserved blocks

Reserved percent

Setup done-058

Select lv-059

Use as-060

Howto use-061

Mount point-062

Select mount-063

Setup done-064

Finish partitions

Write changes-066

Installer now proceeds to install a base system.

3. Install packages

For a home server setup I like to configure automatic security updates. But for my main laptop I handle updates myself …

Updates

For a minimal, console-only setup, leave all the software collections unselected. Otherwise, lots of choices: maybe pick the “[x] Basic Ubuntu server”, the flagship “[x] Ubuntu desktop”, or my current favourite “[x] Ubuntu MATE desktop” …

Select software

4. Boot loader

Near the end of the install process is the GRUB boot loader setup. This is the point where - if you select ‘Yes’ to install GRUB to a hard disk - the installer stumbles over the encrypted boot directory and the install will fail. For now, we choose not to install GRUB to the master boot record …

Grub mbr

Installer will download the GRUB tools but leave the MBR untouched.

Press ALT+F2 and start a new console. Enter the newly-created Ubuntu install using chroot, but before doing so make the installer’s sys directory available to the chroot’ed environment (eliminating “device node not found” errors generated by grub-mkconfig) …

# mount --bind /sys /target/sys

Now, chroot into /target mountpoint …

# chroot /target 

Retrieve the device UUID of the encrypted partition sda1

# ls -al /dev/disk/by-uuid/ | grep sda1

Modify /etc/default/grub

# The "device-uuid" refers to the UUID of /dev/sda1.
GRUB_CMDLINE_LINUX="cryptdevice=UUID=device-uuid:lvm root=/dev/vg/root"

# Enable full disk encryption (including /boot)
GRUB_ENABLE_CRYPTODISK=y

Generate a grub.cfg by running grub-mkconfig

# grub-mkconfig -o /boot/grub/grub.cfg

Generates “WARNING: Failed to connect to lvmetad. Falling back to device scanning” messages. These warnings can safely be ignored.

Confirm grub.cfg has entries insmod cryptodisk and insmod luks

# grep 'cryptodisk\|luks' /boot/grub/grub.cfg

Otherwise, add cryptodisk and luks to GRUB_PRELOAD_MODULES in /etc/default/grub and regenerate grub.cfg.

Now, with the proper configuration, install GRUB to MBR …

# grub-install /dev/sda

5. Finish the install

Unmount /sys and exit chroot …

# umount /sys && exit

Press ALT+F1 to return to installer menu item “Finish the Installation”. Complete remaining steps and reboot …

UTC

Finish install

GRUB prompts for the encryption passphrase.

Three things to note: 1/ passphrase input uses qwerty keyboard (user-set keymap is ignored); 2/ only allowed one chance to get the passphrase correct (will need to reboot otherwise); 3/ during boot, kernel will prompt for the passphrase a second time to unlock the LVM volume (and this time it does use the assigned keymap).

Grub decrypt

Kernel decrypt

Welcome to encrypted Ubuntu!

Login

Links: 1/ LVM on LUKS; 2/ Full disk encryption with LUKS; 3/ Linux Mint encryption

6. Keyfile

Avoid entering the encryption passphrase a second time for the kernel by creating a LUKS keyfile

$ sudo dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
$ sudo cryptsetup luksAddKey /dev/sda1 /crypto_keyfile.bin
$ sudo chmod 000 /crypto_keyfile.bin

Modify /etc/crypttab by changing …

sda1_crypt UUID=xxxx.......... none luks,discard

… to …

sda1_crypt UUID=xxxx......... /crypto_keyfile.bin luks,discard,keyscript=/bin/cat

Create crypto_keyfile and place in /etc/initramfs-tools/hooks with …

#!/bin/sh
cp /crypto_keyfile.bin "${DESTDIR}"

Make the file executable and regenerate the ramdisk …

$ sudo chmod 755 /etc/initramfs-tools/hooks/crypto_keyfile
$ sudo update-initramfs -u -k all

Confirm that the keyfile has been inserted in the ramdisk …

$ sudo lsinitramfs $(ls /boot/initrd.img-*) | grep keyfile

… and reboot. What comes next?

Happy hacking!

  • CC BY-SA image of “Torii Gates” courtesy of BriYZZ