HOWTO: Fully encrypted vServer with Ubuntu 12.04

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.

You can also try this HOWTO under VirtualBox with the System Rescue CD ISO images. Actually, that’s where I verified all steps are working.

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 /boot and /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 /dev/sda2:

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 debootstrap

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 debootstrap

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 grub, chose /dev/sda.

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.

Known problems:

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 /etc/default/grub.

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

7 thoughts on “HOWTO: Fully encrypted vServer with Ubuntu 12.04”

  1. Lols, good for you, then. I guess my passphrase is similarly long as the above described workaround – so what the heck 😉

  2. Hi Martin. me again. Probably getting more visits these days ;-). Have you just tried hitting a couple of times and waiting? The password prompt should show up.

  3. You forgot the boot loader: package “grub2” must be installed (inside the chroot) and “update-grub” must be invoked.

    Furthermore, it is not necessary to append all the modules to the file “/etc/initramfs-tools/modules” manually (initramfs-tools includes most modules by default already).

    Also, if you install packages “busybox” and “dropbear” before running “update-initramfs”, then you will get a remote-unlock via SSH (automatically). This is very useful if there is no remote console, as with many physical root servers.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.