A technical tutorial brought to you by OpenCraft : )
This article was written by team member Alan Evangelista.
This tutorial targets Ubuntu 19.10 and supports older versions down to Ubuntu 16.
Introduction
Your Linux user password prevents unauthorized logins to your Linux installation, but it does not prevent unauthorized access to your hard disk data. For instance, a thief that steals your computer could easily avoid the Linux user password entirely by using a Live CD or moving your hard disk to another computer. Encrypting a hard disk adds a security layer, making much less likely that an attacker that has physical access to your hard drive will be able to recover any data at all. For this reason, this is a requirement for all employees in some tech companies working with Linux such as Opencraft. The downsides are a small performance penalty when accessing the disk and having to remember and type an extra password on every boot.
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 (Linux Unified Key Setup) 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.
Ubuntu 18.04 and above offers to encrypt your hard disk in automated fashion during its installation using dm-crypt and LUKS [1]. However, this option forces you to wipe your entire disk, which is not an option if you already have another operating system installed, such as Windows. This tutorial describes in detail how to encrypt your existing root partition in Ubuntu preserving all disk data. Most commands are Linux distribution-agnostic and should work well in other Linux distributions.
In short, the scenario covered in this tutorial is:
– Your computer has UEFI (Unified Extensible Firmware Interface)
– Your existing Ubuntu installation has a EFI system partition mounted at /boot/efi and a partition mounted at / (root partition)
– You want to encrypt your root partition preserving all the existing data in the hard disk
– Your root filesystem type is EXT3/EXT4.
Most recent motherboards and operating systems support UEFI. You can make sure your computer supports it by booting and checking its firmware. You can check disk partitions using the “fdisk -l” command in a terminal in Linux.
[1] The automated “full-disk” encryption replaces the automated /home encryption available in the installers of Ubuntu 17 and older versions.
Preparation
First, it is recommended to perform a full-disk image backup of the entire hard disk. If anything goes wrong during the encryption, you risk losing all the data in it, so it is better to be safe than sorry.
Second, there is no way to encrypt a mounted partition in Linux and you cannot unmount the root partition from which you have booted, so you will have to boot from a live USB. Take the following steps:
– Download the latest Ubuntu ISO at https://ubuntu.com/download/desktop. I have used Ubuntu 19.10 for this tutorial and therefore the instructions presented here focus on it. If you are using another version, maybe you will have to tweak some commands.
– Build a live USB with the ISO. In Ubuntu 19.10, you can install the usb-creator-gtk package and use the Startup Disk Creator graphic application; simply use the “Other” button to select an ISO file and the “Make Startup Disk” button to create a live USB with it.

– Reboot your workstation, enter your UEFI firmware, set the USB device to boot before the hard disk, save your changes, leave the firmware and boot in the live USB selecting the “Try Ubuntu without installing” in the GRUB menu, as shown in the following image.

Once the Live Desktop Ubuntu environment has started, open a terminal by pressing Ctrl+Alt+T, run “fdisk -l” and look for the partition with the type “EFI system” and approximately 260 MB. That is the EFI system partition. Write down its number. Also look for a partition with the type “Linux filesystem” and write down its number. If you have more than one of these, you can use “mount”, “df”, “lsblk” or “findmnt” to see the mount points of all Linux partitions and pick the one mounted at the root directory.

Notice: most computer nowadays use SATA hard disk drives and Linux names the main SATA hard disk as sda and the partitions in it as sda1, sda2, etc. However, hard disk drives which use other technologies such as PATA or NVM Express will get other device names. I’ll assume that the main hard disk’s Linux device name is sda from now on and you must adjust the commands accordingly if that name is different in your computer.
Get the root partition UUID using the following command, replacing X with the root partition number:
$ blkid -s UUID -o value /dev/sdaX
Write this UUID down.
Encryption
During encryption, a LUKS encryption header is added at the beginning of the partition. 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 it can be 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 or cryptsetup-reencrypt (available in Ubuntu 19 and above) to achieve that. In Ubuntu 19 and above, I recommend the latter because it is more actively supported and therefore that is the one I will use in this tutorial. Make sure you have shrunk the filesystem as explained above before running this or you will lose all the existing data in the root partition. Execute the following command, replacing X with the root partition number:
$ cryptsetup-reencrypt /dev/sdaX --new --reduce-device-size 16M --type=luks1
The default LUKS format used by the cryptsetup tool changed to version 2 in Ubuntu 18.04. GRUB only supports version 1 so make sure you set the LUKS version to 1 as done above or else GRUB will not be able to install to or unlock the encrypted device.
You will be asked to enter a passphrase twice. Make sure you remember it easily because you will need to provide it on every system boot.
Enter new passphrase:
Verify passphrase:
Finished, time (...)
Open the encrypted root partition using cryptsetup (available in Ubuntu 19 and above), replacing X with the root partition number:
$ cryptsetup open /dev/sdaX rootfs
Extend the filesystem of the now encrypted root partition to take up all available space in the partition:
$ resize2fs /dev/mapper/rootfs
Post-encryption: boot adjustments
Although the first-stage GRUB boot loader is in the unencrypted /boot/efi partition, the second-stage GRUB boot loader and the initial ram disk are in /boot and therefore in the encrypted root partition. Due to this, you must make adjustments in GRUB so that it can access those.
Create a change-root environment in the root partition. Execute the following commands, replacing Y with the number of the EFI system 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
With the current setup, the system would ask the encryption passphrase twice: once to access the second-stage GRUB boot loader and once again for the Linux kernel to access the encrypted root partition when it boots. In order not to require typing the encryption passphrase the second time, a keyfile must be created, added to LUKS and set up in /etc/crypttab, which describes the encrypted block devices that are set up during system boot.
Execute the following commands:
$ mkdir /etc/luks
$ dd if=/dev/urandom of=/etc/luks/boot_os.keyfile bs=4096 count=1
$ chmod u=rx,go-rwx /etc/luks
$ chmod u=r,go-rwx /etc/luks/boot_os.keyfile
$ cryptsetup luksAddKey /dev/sdaX /etc/luks/boot_os.keyfile
Add the following line to /etc/crypttab (replace <encrypted_rootfs_uuid> with the root partition UUID):
rootfs UUID=<encrypted_rootfs_uuid> /etc/luks/boot_os.keyfile luks,discard
Example:

Remove the existing root partition line from /etc/fstab and add the following line:
/dev/mapper/rootfs / ext4 errors=remount-ro 0 1
Example:

In /etc/default/grub, remove the existing reference to the root partition from GRUB_CMDLINE_LINUX and add the following line:
GRUB_ENABLE_CRYPTODISK=y
This line makes grub-install generate additional commands needed to access the encrypted root partition during boot.
Example:

Update GRUB binary and configuration files:
$ 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 Ubuntu menu entry which loads the luks and cryptodisk kernel modules and mounts the encrypted partition using cryptomount.
Example (click on image for bigger version):
Update the initial RAM disk:
$ update-initramfs -k all -c
Leave the change-root environment:
$ exit
Unmount all mounted filesystems:
$ umount -a
Reboot and remove the USB drive so that the computer boots from the hard disk. You will be prompted to type the encrypted root partition passphrase.

Type the passphrase and Ubuntu will boot. That’s it!
If you have any suggestions or comments about this tutorial, feel free to add them in comments : )
Comments
Leave a ReplyWonderful tutorial. Unfortunately in Ubuntu 18.04.5 LTS the cryptsetup-reencrypt just fails silently:
root@xxx:/root# cryptsetup-reencrypt /dev/sdb1 –new –reduce-device-size 16M
Enter new passphrase:
Verify passphrase:
root@xxx:/root# echo $?
1
root@xxx:/root#
Error code 1 means “invalid parameter” by the man page. Quite cryptic if you ask me.
Hello Indrek!
Sorry for the late reply.
It seems like the formatting of the blog post affected the command. The “new” and “reduce-device-size” options should be preceded with two dashes (-) and not just a single one.
There’s also a chance that the formatting of the blog affected the characters, so if the previously mentioned change doesn’t work, would please try typing the dashes from your keyboard?
Please let us know if that works.
We’ll also make sure to make the necessary changes so similar issues don’t happen.
Hey Indrek,
Thanks for your comment. I’ll share with the team and we’ll get back to you!
Hi Alan,
I had an issue while following this tutorial where GNOME had an error and crashed. The result was that I managed to encrypt my partition but I wasn’t able to decrypt it using my passphrase.
My question is, is this tutorial still up to date for Ubuntu 20.1? I’ve noticed that other tutorials are much longer on the same topic. Does this tutorial skip some steps?
Hi Ryan,
Alan doesn’t work at OpenCraft anymore, but I’ll schedule a task for another developer to answer you. We’re in the middle of a busy sprint right now, but we’ll get back to you asap!
Hello Ryan,
It seems like other Gnome users have faced a similar issue with gnome-shell crashing in Ubuntu 20.1.
Unfortunately, this tutorial doesn’t seem to be up to date for Ubuntu 20.1. It was intended for Ubuntu 16.04 and 18.04.
We’re sorry that the blog post doesn’t explicitly state that. We’ll be sure to update it as soon as possible with the targeted Ubuntu releases.
Q for Ubuntu 20.04.2 LTS: I worked thru this until the very last command:
$ update-initramfs -k all -c
This produced 2x this error message:
update-initramfs: Generating /boot/initrd.img-5.8.0-43-generic
cryptsetup: ERROR: rootfs: Source mismatch
cryptsetup: WARNING: Skipping root target rootfs: uses a key file
After “exit”, the “umount -a” reported that it could not unmount some mount points.
After reboot, the machine queried for the passphrase (good) and after a while it displayed
GRUB>
Not good.
Naturally I do not have a full log of my actions, but all steps seemed to be completed as described and expected. For editing text files like fstab I used “nano”. What may be wrong here?
Additional info: The machine has NVME SSD drive. Initial install had to be tweeked since regular “install & update” routine left it frozen. In fact I do not know how that was fixed, but somehow it was.
Hello Christian! The reason things didn’t work as expected is that the tutorial isn’t up to date for Ubuntu 20.04. As mentioned in the blog post, the post targets Ubuntu 19 and supports versions down to 16.04. Sorry for the inconvenience!
I was able to use this tutorial with a few minor changes on ubuntu 20.04 LTS. It was done on Dell Alienware m15 R6 laptop with NVIDIA GeForce RTX 3060 GPU.
Here are the ubuntu details (after initial install and apt update/upgrade):
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
$ uname -a
Linux laptop 5.11.0-38-generic #42~20.04.1-Ubuntu SMP Tue Sep 28 20:41:07 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
I also made sure I installed the cryptsetup package (this is very important since it may not be part of the initial ubuntu install)
$ sudo apt update
$ sudo apt install cryptsetup
I followed the instructions up to cryptsetup open:
root@ubuntu:/home/ubuntu# cryptsetup open /dev/nvme0n1p7 rootfs
Enter passphrase for /dev/nvme0n1p7:
root@ubuntu:/home/ubuntu# resize2fs /dev/mapper/rootfs
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/mapper/rootfs to 8187904 (4k) blocks.
The filesystem on /dev/mapper/rootfs is now 8187904 (4k) blocks long.
Here I ran lsblk -f to note both encrypted and decrypted UUIDs:
root@ubuntu:/home/ubuntu# lsblk -f
…
└─nvme0n1p7 crypto_LUKS xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
└─rootfs ext4 yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
crypto_LUKS line shows encrypted UUID
ext4 line shows decrypted UUID (the same as it was at the start)
I continued with mount commands all the way to cryptsetup that adds a keyfile. Along the way I generated the key file using 4096 bits not bytes, i.e. I used bs=512 for ‘dd’ command. So, the key file was 512 bytes (4096 bits) long. I don’t know if this would be relevant, but I thought that 4096 bytes was excessive.
root@ubuntu:/# cryptsetup luksAddKey /dev/nvme0n1p7 /etc/luks/boot_os.keyfile
Enter any existing passphrase:
HERE IS THE MISSING PART FOR 20.04 LTS:
==================================
root@ubuntu:/# echo “KEYFILE_PATTERN=/etc/luks/*.keyfile” >> /etc/cryptsetup-initramfs/conf-hook
root@ubuntu:/# echo “UMASK=0077” >> /etc/initramfs-tools/initramfs.conf
==================================
That part I figured out after carefully reading the ubuntu documentation (Full Disk Encryption Howto 2019).
Next I updated the crypttab making sure I used the ENCRYPTED UUID:
root@ubuntu:/# cat /etc/crypttab
#
rootfs UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /etc/luks/boot_os.keyfile luks,discard
I updated the /etc/fstab as described in tutorial and finished up with the grub and update-initramfs. Same as in the tutorial.
I noted that the /boot/grub/grub.cfg was not exactly the same as in the tutorial. The linux command did not have the cryptdevice before the “quite splash” which I actually removed anyways. In the end that did not matter.
Finally I did exit and did not bother to umount since that would not work anyways. The update-initramfs showed me a few warnings that did not seem to matter. Or, at least I did not experience any problems in the subsequent usage of the system.
root@ubuntu:/etc/default# update-initramfs -k all -c
update-initramfs: Generating /boot/initrd.img-5.11.0-38-generic
W: Possible missing firmware /lib/firmware/i915/skl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/bxt_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/kbl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/glk_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/kbl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/kbl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/cml_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/icl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/ehl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/ehl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/tgl_huc_7.5.0.bin for module i915
W: Possible missing firmware /lib/firmware/i915/tgl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/tgl_huc_7.5.0.bin for module i915
W: Possible missing firmware /lib/firmware/i915/tgl_guc_49.0.1.bin for module i915
W: Possible missing firmware /lib/firmware/i915/dg1_dmc_ver2_02.bin for module i915
update-initramfs: Generating /boot/initrd.img-5.4.0-26-generic
I completed with “$ reboot -f now” and after providing the passphrase the system properly booted. That’s was it!
I hope this would be helpful to other people.