I am writing this mostly as a note to self, to document the various subtleties of setting up an Ubuntu installation with full-disk encryption using LVM over LUKS+dmcrypt, on a solid-state drive. All this information is already on the net, but seems to be mostly spread in various forums as answers to specific questions, so I felt it would be useful (for me, certainly) to have all the information in a single place for future reference. It is such a waste to have to solve the same problem again in the future. In my case I already had a working installation so I only needed to restore the partition contents from backups and reinstall the boot-loader, all from a live USB. The same issues apply for a clean install.
Now you may be wondering why bother with full-disk encryption on an SSD, when some (or many, I’m not sure) modern drives have hardware encryption anyway. Or even why bother with full-disk encryption on a desktop. Well, starting with the latter question I think the real question should be ‘why no?’. After all, encryption nowadays basically costs nothing, and I for one would rather not bother about personal data in case of theft (particularly for portable devices) or return to manufacturer under warranty. With respect to hardware encryption, while the SSD drive I am working with does support this, Intel chose to only supply the necessary software for Windows, and frankly I find it simpler to use what I’m already used to.
So, the relevant issues in this scenario are:
- We need to make sure the OS boots when we’re done. For the Ubuntu 12.04 LTS system that I am using, this means that the boot partition cannot be within the encrypted-LVM setup. The version of GRUB that comes with this OS does support boot on LVM, but not boot on encrypted LVM.
- We need to make sure that TRIM commands can pass through all levels. In order: a) we need to use a filesystem that allows discards and enable them on mount, b) we need to make sure LVM understands discards and passes them through, and c) we need to set up LUKS+dmcrypt to pass discards through.
- We also need to make sure that any available hardware acceleration for encryption is used. Specifically, most modern processors have specific commands for AES within their microcode, and this significantly speeds up dmcrypt, which knows how to use it. This requires loading a specific kernel module at bootup. It is particularly relevant on SSDs because they are fast enough to make the difference in encryption speed significant.
So the simplest solution is to set up the the SSD as follows (assuming the SSD is on /dev/sda):
- Boot up with a live USB (I used the Ubuntu 12.04 LTS desktop live ISO); when creating the bootable USB you’ll need to leave some persistent space. On first boot install the lvm2 package to allow you to set up LVM. Open a terminal and initiate root mode (sudo -i) for the following.
- Set up a first partition for boot (say 512M) on /dev/sda1.
- Set up the rest of the SSD as a single logical partition on /dev/sda5.
- Set up /dev/sda5 as an encrypted partition:
cryptsetup luksFormat /dev/sda5 cryptsetup luksOpen --allow-discards /dev/sda5 sda5_crypt
- Set up the encrypted partition as a physical volume for LVM:
- Set up a volume group using this physical volume:
vgcreate sysvg /dev/mapper/sda5_crypt
- Create the necessary partitions within this volume group, for example:
lvcreate -n root -L 4G sysvg lvcreate -n var -L 4G sysvg lvcreate -n usr -L 16G sysvg
- Format the new system partitions with a filesystem that understands discards:
mkfs.ext4 /dev/sda1 mkfs.ext4 /dev/sysvg/root mkfs.ext4 /dev/sysvg/var mkfs.ext4 /dev/sysvg/usr
- Mount the new filesystems and restore the relevant backup, for example (this needs to be repeated for each partition, of course):
mount -o noatime,discard /dev/sda1 /mnt cd /mnt restore -rf /path/to/boot.0
- Set up the OS so that it sets up the necessary settings on bootup. Set up LUKS to enable discards by adding a line to /etc/crypttab (for the SSD filesystem) containing:
sda5_crypt UUID=xxxxxx none luks,discard
You can find the UUID for the sda5 partition using:
Technically you can replace the UUID string with just /dev/sda5, but if the order of hard disks changes on bootup you’re asking for trouble. Next you need to enable discards and noatime for the filesystems, on mount. Do this by editing /etc/fstab (again, for the SSD filesystem):
/dev/sda1 /boot ext4 defaults,noatime,discard 0 2 /dev/sysvg/root / ext4 noatime,discard,errors=remount-ro 0 1 /dev/sysvg/var /var ext4 defaults,noatime,discard 0 2 /dev/sysvg/usr /usr ext4 defaults,noatime,discard 0 2
- Re-install GRUB on the SSD’s MBR:
- Next step is to reboot and hope that everything works…
- If you have a recent processor that has the AES microcode (you can check this with grep aes /proc/cpuinfo), enable this by adding the aesni-intel module to /etc/initramfs-tools/modules; then update the ramdisks:
update-initramfs -u -k all
- You can test that the AES microcode is doing its job by comparing the speeds of the encrypted volume and its underlying SSD volume:
hdparm -t /dev/sda5 hdparm -t /dev/mapper/sda5_crypt
The first line gives you the access speed of the SSD, the second does the same for the SSD with overlying encryption. On my setup (Core i5-3570K CPU and Intel 330-series SSD), the two speeds are almost the same.