Update 2022-05-16: Today I learned that there are two official tutorials by Hetzner for Ubuntu 20.04. You might want to follow them instead:
- How to install Ubuntu 20.04 with full disk encryption
- How to install an encrypted ubuntu20.04 with automated unlocking via tang and clevis
In this blog post I am going to demonstrate how to easily setup a virtual server at Hetzner. This setup will work for most other vServer operators as well, but some adjustments may be required. Prerequisite is that you are able to access the console of the server while booting, as you need to be able to enter the passphrase. You also need to be able to boot into some sort of “Rescue System” for the setup. This is no in-place setup. In Hetzner’s “Robot” this is pretty easy.
One thing to consider regarding security: fully encrypting a vServer might seem… senseless, as the host operator can easily copy the whole memory of the VM while running and extract the key this way. True. There is no way around this fact. My reason for wanting a fully encrypted system is more of the way that I want to be sure that the data is encrypted on the storage system. I want to protect from being unable to ever fully wipe the persistent data from disk in case I cancel the VM, the VM gets moved to a new host, or a failed disk is sent in to the manufacturer. For me, this is a compromise I can accept. YMMV.
So, let’s dive into the fun of the HOWTO. BEWARE! THIS TUTORIAL WILL WIPE ALL DATA ON YOUR VSERVER! I TAKE NO RESPONSIBILITY IF YOU LOSE DATA! IT MIGHT ALSO NOT WORK FOR YOU. USE THIS AT YOUR OWN RISK!
The following steps will partition the disk, setup LVM and LUKS, install Ubuntu 12.04 and prepare the system for reboot. Most parts can be copied line-by-line. Please beware that there are some parts in this tutorial that needs to be adjusted: UUIDs of partitions, hostname, username, and most important: network setup.
The following steps were performed for my Hetzner VQ7 instance directly after ordering it:
1. Reboot into Rescue System.
2. Partition the disk using
cfdiskd /dev/sda or
fdisk /dev/sda, whichever you prefer.
You need two paritions,
sda1 with about 256MB, which needs to be marked bootable and which later will be mounted as
/dev/sda2 which should be the rest of the disk. This will be the LUKS container, which will then ultimately host the LVM with all other partitions.
3. Create LUKS container on
apt-get install cryptsetup cryptsetup luksFormat /dev/sda2
At this point you need to confirm that you really want to wipe all data on
/dev/sda2 and then enter your encryption password, twice. Use a secure password here! Your entire encryption depends on this password.
4. Open the LUKS container and initialize an LVM volume group on the decrypted partition:
cryptsetup luksOpen /dev/sda2 sda2_decrypt vgcreate vg-encrypted /dev/mapper/sda2_decrypt
5. Create swap and root partitions in LVM and create file-systems:
lvcreate -L 2G -n swap vg-encrypted lvcreate -L 10G -n root vg-encrypted mkfs.ext2 /dev/sda1 mkswap /dev/vg-encrypted/swap mkfs.ext4 /dev/vg-encrypted/root
I normally tend to only use the space I will likely need in short-term for root, as on LVM and with
ext4 you can always re-size the file-system even while the file-system is mounted. Keeping unallocated space in the volume-group provides more flexibility, like being able to add other partitions on demand, or cool features like LVM snapshots which can be quite handy for doing crash-consistent backups of the host.
6. Record UUIDs of partitions
You will need them later on:
blkid /dev/sda1 /dev/sda2 /dev/vg-encrypted/root /dev/vg-enrypted/swap
This will output something similar to the following:
/dev/sda1: UUID="e789d69e-1a90-492d-8a1e-1f719a3b754e" TYPE="ext2" /dev/sda2: UUID="f25ad69c-5c6e-4f35-b305-a8b193d58111" TYPE="crypto_LUKS" /dev/vg-encrypted/root: UUID="d9f21bd7-508b-4404-916e-50fcc6b73f12" TYPE="ext4" /dev/vg-encrypted/swap: UUID="e4c91de1-ad8d-4e05-9cee-2803d45840a2" TYPE="swap"
I will use this UUIDs for the rest of this HOWTO, be sure to replace them with your’s, wherever they are used below.
7. Mount target system for
mkdir -p /mnt/ubuntu && \ mount /dev/vg-encrypted/root /mnt/ubuntu && \ mkdir /mnt/ubuntu/boot && \ mount /dev/sda1 /mnt/ubuntu/boot
8. Download and install
cd wget 'http://archive.ubuntu.com/ubuntu/pool/main/d/debootstrap/debootstrap_1.0.42_all.deb' && \ ar x debootstrap_1.0.42_all.deb && \ cd / && \ tar xzf /root/data.tar.gz
This will download
debootstrap 1.0.42 which can install Ubuntu 12.04 (Precise) and install it in root of the rescue system.
9. Bootstrap Ubuntu onto the target disk
debootstrap --arch amd64 precise /mnt/ubuntu
This will download and install the base packages for an Ubuntu 12.04 system and install it in
/mnt/ubuntu, which is the root partition inside the encrypted LVM. This can take some time… Please also note that you need to bootstrap amd64 or the 32bit version, dependent of the rescue system you booted.
10. Mount / bind virtual filesystems and enter chroot
mount -t proc none /mnt/ubuntu/proc mount -o bind /dev /mnt/ubuntu/dev mount -o bind /sys /mnt/ubuntu/sys cp /etc/resolv.conf /mnt/ubuntu/etc/ LANG=C chroot /mnt/ubuntu /bin/bash
11. Configure disks, network, and hostname
Attention! This are now sections that you MUST adapt for your system!
echo " UUID=d9f21bd7-508b-4404-916e-50fcc6b73f12 / ext4 defaults,noatime 0 0 UUID=e789d69e-1a90-492d-8a1e-1f719a3b754e /boot ext2 defaults,relatime 0 1 UUID=e4c91de1-ad8d-4e05-9cee-2803d45840a2 none swap sw 0 0 proc /proc proc defaults 0 0 sys /sys sysfs defaults 0 0 " > /etc/fstab echo MYHOSTNAME > /etc/hostname echo "127.0.0.1 localhost 127.0.1.1 MYHOSTNAME ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters " > /etc/hosts echo "# interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.15.105 netmask 255.255.255.0 gateway 192.168.15.1 " > /etc/network/interfaces
11. Configure Ubuntu mirror
For Hetzner, you can use the following setup:
echo "# Packages and Updates from the Hetzner Ubuntu Mirror deb ftp://mirror.hetzner.de/ubuntu/packages precise main restricted universe multiverse deb ftp://mirror.hetzner.de/ubuntu/packages precise-updates main restricted universe multiverse deb ftp://mirror.hetzner.de/ubuntu/security precise-security main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu precise main deb-src http://archive.ubuntu.com/ubuntu precise main deb http://security.ubuntu.com/ubuntu precise-security main deb-src http://security.ubuntu.com/ubuntu precise-security main " > /etc/apt/sources.list
12. Install essential packages (Kernel, OpenSSH, …)
dpkg-reconfigure tzdata apt-get update apt-get install aptitude openssh-server apt-get install linux-image-generic apt-get install cryptsetup lvm2
If you are asked where to install
13. Setup LUKS for boot
echo "# <target name> <source device> <key file> <options> sda2_decrypt UUID=f25ad69c-5c6e-4f35-b305-a8b193d58111 none luks " > /etc/crypttab echo "dm-crypt" >> /etc/modules echo "aes" >> /etc/initramfs-tools/modules echo "aes_i586" >> /etc/initramfs-tools/modules echo "aes_x86_64" >> /etc/initramfs-tools/modules echo "aes_generic" >> /etc/initramfs-tools/modules echo "dm-crypt" >> /etc/initramfs-tools/modules echo "dm-mod" >> /etc/initramfs-tools/modules echo "sha256" >> /etc/initramfs-tools/modules echo "sha256_generic" >> /etc/initramfs-tools/modules echo "lrw" >> /etc/initramfs-tools/modules echo "xts" >> /etc/initramfs-tools/modules echo "crypto_blkcipher" >> /etc/initramfs-tools/modules echo "gf128mul" >> /etc/initramfs-tools/modules update-initramfs -u -k all
13. Create a user
adduser myuser addgroup --system admin adduser myuser admin
14. Exit chroot, umount, and reboot
Basically we are done now. We can leave chroot, reboot the system.
When the server reboots, observe it in the console, you’ll need to enter the password anyways.
I have experienced that after the latest kernel update for some reasons the prompt for the password does no longer work. In this case I disabled
quiet splash in
I also currently am having an issue that the encrypted container is not recognized by the initramfs, so it falls to busybox. If I open the LUKS container there manually and scan for LVM, and then exit the busy box, boot resumes as it should.
cryptsetup luksOpen /dev/sda2 sda2_decrypt lvm vgchange -a y exit