I have documented the steps I have recently taken to encrypt the existing root EXT4 partition of my Ubuntu 19.10. I hope it can be helpful to other newcomers. Improvements suggestions are welcome. Should I add it to some wiki/git repository?
Scenario:
- You have a EFI system partition mounted at /boot/efi and a partition mounted at / (root partition) and want to encrypt the latter preserving the existing data.
- The root filesystem type is EXT3/EXT4.
I used Ubuntu 19.10 and therefore the instructions are focused on it. If you are using a different distribution, maybe you’ll have to tweak some commands.
First, Linux has multiple disk encryption solutions. Two of the most popular ones nowadays are dm-crypt with LUKS and ecryptfs. dm-crypt provides “block” level encryption. With it, the Linux kernel creates an entire encrypted block device, which can then be used like any other block device in the system. LUKS is a disk encryption specification which is widely used in Linux together with dm-crypt. On the other hand, eCryptfs provides “per-file” encryption. It stores encryption metadata in the header of each file and there is no need to keep track of any additional information aside from that. Since eCryptfs has to process keys and metadata on a per-file basis, usually dm-crypt is faster than ecryptfs and that’s why I have chosen to use it.
Second, there is no way to encrypt a mounted partition in Linux and you cannot unmount the root partition from which you booted, so you’ll have to boot from a live USB. Steps:
- Download the ISO of the latest version of your favorite Linux distribution (I chose Ubuntu 19.10).
- Build a live USB with the ISO (in Ubuntu 19.10, you can install usb-creator-gtk and use the Startup Disk Creator graphic application).
- Reboot your workstation, set the USB device to boot before the hard disk in your BIOS and boot in the live USB.
Write down the number of the EFI system partition. If you don’t know the partition number, check it with the “fdisk -l” command and look for the partition with type “EFI system” and approximately 260 MB.
Write down the number and the UUID of the root partition. If you don’t know the partition number, check it with the “fdisk -l” command. If you don’t know the partition UUID, check it with the “blkid” command.
During encryption, a LUKS encryption header is added at the beginning of the device. Since an existing filesystem will usually use the entire partition, you must shrink it to make space for the LUKS header. Furthermore, resize2fs, the tool used to resize EXT2/EXT3/EXT4 filesystems, requires the filesystem to be checked before resized. Execute the following commands, replacing X with the root partition number:
$ e2fsck -f /dev/sdaX
$ resize2fs -M /dev/sdaX
Encrypt your unencrypted root partition using LUKS1. You can use luksipc (https://github.com/johndoe31415/luksipc) or setupcrypt-reencrypt (available in Ubuntu 19+) to achieve that. I recommend the latter because it is more actively supported. You will be asked to enter a passphrase, which you will have to provide on every system boot. Remember to replace X with the root partition number. Make sure you have shrunk the filesystem as explained above before running this or you will will lose all the existing data in the root partition.
$ cryptsetup-reencrypt /dev/sdaX --new --reduce-device-size 16M --type=luks1
Enter new passphrase:
Verify passphrase:
Finished, time (…)
Open the encrypted root partition using cryptsetup (available in Ubuntu 19+). Replace X with the root partition number.
$ cryptsetup open /dev/sdaX rootfs
Extend the filesystem of the now encrypted partition to occupy all available space in the partition.
$ resize2fs /dev/mapper/rootfs
Fix the system boot:
-
create a chroot in the root partition. Replace Y with the number of the boot partition.
$ mount /dev/mapper/rootfs /mnt
$ mount /dev/sdaY /mnt/boot/efi
$ mount --bind /dev /mnt/dev
$ mount --bind /dev/pts /mnt/dev/pts
$ mount --bind /sys /mnt/sys
$ mount --bind /proc /mnt/proc
$ chroot /mnt -
add the following line to /etc/crypttab (replace <encrypted_rootfs_uuid> with the root partition UUID):
rootfs UUID=<encrypted_rootfs_uuid> none luks
-
comment/remove the existing root partition line from /etc/fstab and add the following line:
/dev/mapper/rootfs / ext4 errors=remount-ro 0 1
-
comment/remove the existing GRUB_CMDLINE_LINUX from /etc/fstab and add the following lines to it (replace <encrypted_rootfs_uuid> with the root partition UUID) :
GRUB_ENABLE_CRYPTODISK=y
GRUB_CMDLINE_LINUX=“cryptdevice=UUID=<encrypted_rootfs_uuid>:rootfs” -
update GRUB configuration files/binary:
$ grub-install
$ update-grub
-
Make sure that the GRUB configuration file at /boot/grub/grub.cfg was updated correctly by update-grub. There must be at least a menu entry which loads the kernel modules luks and cryptodisk, mounts the encrypted partition using cryptomount and sets the kernel option “cryptdevice=UUID=<encrypted_rootfs_uuid>:rootfs” . Example:
menuentry ‘Ubuntu’ (…) {
(…)
insmod cryptodisk
insmod luks
(…)
cryptomount -u <encrypted_rootfs_uuid>
set root=‘cryptouuid/<encrypted_rootfs_uuid>’
(…)
linux /boot/vmlinuz-5.3.0-29-generic root=UUID=<unencrypted_rootfs_uuid> ro cryptdevice=UUID=<encrypted_rootfs_uuid>:rootfs quiet splash $vt_handoff
initrd /boot/initrd.img-5.3.0-29-generic -
update the initial RAM disk:
$ update-initramfs -k all -c
-
leave the chroot
$ exit
-
unmount all mounted filesystems
$ umount -a
Reboot from the hard disk. You will be prompted to type the passphrase and then Linux will boot. An undesired result of this setup is that the encryption passphrase is requested twice during boot.