Floating Octothorpe

Building a NAS: part 2 - OS encryption

Following on from last weeks post, Ubuntu 20.04 is finally out. This post is going to go over installing Ubuntu server and setting up full disk encryption.

Setting up a USB key

Setting up a Ubuntu USB key to boot from is fairly straight forward. Canonical have published a guide for Windows and Ubuntu. Alternatively dd can be used with the following steps:

  1. Download the ISO file from ubuntu.com.
  2. Verify the download:

    echo "caf3fd69c77c439f162e2ba6040e9c320c4ff0d69aad1340a514319a9264df9f *ubuntu-20.04-live-server-amd64.iso" | shasum -a 256 --check
    
  3. Find the USB drive you want to copy the ISO to:

    lsblk
    
  4. Copy the ISO to the drive

    sudo dd if=ubuntu-20.04-live-server-amd64.iso of=/dev/sdX bs=1M status=progress
    

    Note: this will overwrite any existing data on the drive!

Installing Ubuntu server

Canonical publish Installation instructions for Ubuntu Server. The initial installation process is relatively straightforward, for reference I used the following settings during installation:

  1. Select English as my preferred language.
  2. Use English (UK) for my keyboard layout.
  3. Use DHCP for network configuration.
  4. Install onto the 40GB SSD drive, selecting Encrypt with LUKs.
  5. Setup a user called user.
  6. Set the server's hostname.
  7. Install OpenSSH server, but no snap packages.

If everything goes well, you should be able to remove the USB drive and reboot into the Ubuntu server installation.

Booting without a pass phrase

During the boot process Ubuntu will prompt for the LUKS pass phrase to decrypt the OS drive. If you don't normally have a keyboard and monitor attached, this could quickly become a problem. One way around this is loading a key from a USB drive. This can be done with the following steps

  1. Switch up to the root user:

    sudo -i
    
  2. Attach the USB drive you want to use to store the decryption key, and identify it with lsblk:

    lsblk
    
  3. Create a new file system on the USB drive:

    parted /dev/sdb mklabel msdos
    parted /dev/sdb mkpart primary 0% 100%
    mkfs.ext4 /dev/sdb1
    

    Note: this will remove any existing files on the drive!

  4. Mount the new file system:

    mount /dev/sdb1 /mnt
    
  5. Create a new key for LUKS and set restrictive file permissions:

    dd if=/dev/urandom of=/mnt/boot.key bs=1024 count=4
    chmod 400 /mnt/boot.key
    chown root: /mnt/boot.key
    
  6. Add the new key to the LUKS partition:

    cryptsetup -v luksAddKey /dev/sda5 /mnt/boot.key
    cryptsetup luksDump /dev/sda5
    
  7. Update /etc/crypttab to use the key file:

    export $(blkid --output export /dev/sdb1)
    sed -i.backup "s| none luks.*$| /dev/disk/by-uuid/${UUID}:boot.key luks,keyscript=/lib/cryptsetup/scripts/passdev|" /etc/crypttab
    diff /etc/crypttab /etc/crypttab.backup
    

    Note: make sure you're happy with the changes to /etc/crypttab before rebooting.

  8. Update grub so LUKS is only used by initramfs, this will prevent systemd trying to process the crypttab configuration later on in the boot process:

    echo 'GRUB_CMDLINE_LINUX="rd.luks.crypttab=yes luks.crypttab=no"' > /etc/default/grub.d/cmdline_linux.cfg
    update-grub
    
  9. Update the initramfs image to include the new configuration:

    update-initramfs -k all -u
    
  10. Optional: if you're happy everything is working correctly you can remove the pass phrase keyslot. After doing this you will only be able to decrypt the OS disk with the key file:

    cryptsetup --key-file /mnt/boot.key luksKillSlot /dev/sda5 0
    

    Note: you may prefer to keep the pass phrase as an alternative way to decrypt the OS drive.

Once the steps above are complete, the system should boot and use the key file on the USB drive to decrypt the OS. After the system has been booted you can safely remove the USB drive. It's also a good idea to backup the key file so you can decrypt the drive if you lose the USB key.