Encrypting an Unencrypted Ubuntu Installation
My Ubuntu partition was not encrypted.
I can’t quite recall why, but I believe it had something to do at the time with UEFI and luks installations on Ubuntu not playing nicely.
So recently I decided it was time to migrate to a fully encrypted system, but I didn’t want to lose all my configurations, applications and everything else that comes with an OS that has been tweaked to your liking for the past few years.
My system is EFI, with Ubuntu installed all on one partition. / (root), /boot and /home all on the same partition. If your system is different you may need to adapt some parts of this guide, but in general this should guide you through.
So I started searching for the best way to go about this. To my surprise this doesn’t seem to come up all that often, however I was able to find a old article, that detailed this on a debian system. Ubuntu is debian based, so close enough. https://debian-administration.org/article/577/How_To_Migrate_to_a_full_encrypted_LVM_system
However this didn’t quite cut it, so I “shopped” around for other material. Below are the exact steps you need to follow to be able to migrate successfully.
I didn’t follow these exact steps, as for me there was some learning and trial and error involved at the beginning, but this is the equivalent of what I did but condensed down.
Let me just say that the ARCH Linux Wiki is one of the best resources out there, and a lot of it applies to other distributions as well.
WARNING: BEFORE YOU PROCEED MAKE A FULL BACKUP OF YOUR DISC.
You can do this using, my personal favourite dd, or clonezilla for example. For instructions see: https://wiki.archlinux.org/index.php/disk_cloning
Fyi I have a PCIe SSD.
My partitions before embarking on this journey looked like this:
nvme0n1
├─nvme0n1p1 fat32
├─nvme0n1p2 unknown
├─nvme0n1p3 ntfs
├─nvme0n1p4 ntfs
├─nvme0n1p5 ext4
├─nvme0n1p6 ntfs
└─nvme0n1p7
└─swap swap
From now on we are always referring to the device nvme0n1 located in /dev/nvme0n1, so I will refer only to each partition as p followed by the number.
- p1 is my EFI partition and for simplicity I opted to not touch it, according to this article from ARCH Linux, I could have opted to place /boot on it, instead I opted to place it on a new partition.
- p2-p4 Windows
- p2 – Windows reserved partition.
- p3 – Windows 10
- p4 – Windows recovery (I believe)
- p5 Ubuntu (included /boot)
- p6 NTFS partition with misc Data shared, that I use to share between Ubuntu and my Windows Installation.
- p7 is my encrypted swap partition that I setup up a year ago. If you want to get something like this setup see: https://wiki.archlinux.org/index.php/Dm-crypt/Swap_encryption
NOTE: Remember to backup your disk before proceeding.
In my case I opted to get rid of Windows installation, but you can always nuke your own Ubuntu installation as long as you’ve backed it up of course.
This meant deleting p2, p3 and p4. With this space unallocated I could now create space for my /boot partition and my / (root) partition.
As previously mentioned I opted to create a boot partition of 500MB where I will place my /boot files. Your /boot partition cannot be encrypted, otherwise you would have no way to boot the system.
/boot contains your initramfs images, which you can think of as a mini system, that contains the basics needed to load your full system from disk.
After creating /boot and / (root) partition, I ended up with the following layout.
nvme0n1
├─nvme0n1p1 fat32
├─nvme0n1p2 ext4
├─nvme0n1p3 irrelevant
├─nvme0n1p5 ext4
├─nvme0n1p6 ntfs
└─nvme0n1p7
└─swap swap
Your device might have a different name, that doesn’t matter.
p1, p2, p3, etc identify the partitions.
p2 is formatted as ext4, p4 is irrelevant since we will need to change it to a luks partition.
For this part I followed the ARCH wiki https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS
So on your OS partition, /dev/nvmen0n1p3, run:
cryptsetup luksFormat --type luks2 /dev/nvmen0n1p3 cryptsetup open /dev/nvmen0n1p3 cryptlvm
Remember this will have to be run as root so either add sudo to every command or just open a root shell.
The name cryptlvm doesn’t really matter here, as that’s just the name you are using to open the luks partition.
pvcreate /dev/mapper/cryptlvm vgcreate UbuntuCrypt /dev/mapper/cryptlvm
UbuntuCrypt is the name of your volume and renaming it is possible, but not worth the hassle, so just choose wisely now.
lvcreate -l 100%FREE UbuntuCrypt -n root mkfs.ext4 /dev/UbuntuCrypt/root
Here is where we defer from ARCH, since I had previously setup my swap encrypted. The way I have setup my swap though does not allow me hibernate, since the swap partition key is randomised everytime. If you wish to hibernate I suggest you go ahead and create a swap lvm partiton along inside our newly created luks partition. See the linked ARCH docs for this.
Why LVM over LUKS? For me the simplest answer is at boot time you only have to input the password once.
Once this is done we can now move our system to the new partition.
But first we need to mount our new lvm partition
mount /dev/mapper/UbuntuCrypt-root /mnt
The name of the partition is the name of the lvm volume + ‘-‘ + the name give in lvcreate after ‘-n’, in our case root.
So now we can copy the contents over, rsync is a good tool for this. These are the folders I ended up moving, if you don’t have them all don’t worry.
rsync -a /bin /mnt rsync -a /etc /mnt rsync -a /home /mnt rsync -a /initrd.img /mnt rsync -a /initrd.img.old /mnt rsync -a /lib /mnt rsync -a /lib32 /mnt rsync -a /lib64 /mnt rsync -a /opt /mnt rsync -a /root /mnt rsync -a /sbin /mnt rsync -a /srv /mnt rsync -a /usr /mnt rsync -a /var /mnt rsync -a /vmlinuz /mnt rsync -a /vmlinuz.old /mnt
-a preserves permissions and ownership which you definitely want, if you expect this to work.
There was one final folder which caused more issues.
mkdir /mnt/snap if [[ $(ls -ld /snap | cut -d ' ' -f 1) == $(ls -ld /mnt/snap | cut -d ' ' -f 1) ]]; then echo "true"; else echo "false"; fi;
Proceed if true otherwise change permissions on /mnt/snap to match /snap
rsync -a /snap/bin /mnt/snap rsync -a /snap/sublime-text /mnt/snap
I had to end up copying bin and sublime-text, otherwise my sublime would not startup. However /snap/core was recreated without issues.
I suspect if you have other apps in /snap/APP you might want to move those too as the app might not handle it gracefully.
Now we need to move the boot files.
Now we check if we can boot our new system, but first we need to make some changes to our initramfs.
lsblk -f
nvme0n1
├─nvme0n1p1 vfat ESP ID /boot/efi
├─nvme0n1p2 ext4 ID /boot <-- also relevant
└─nvme0n1p3 crypto_LUKS ID <-- relevant ID
└─UbuntuCrypt LVM2_member ID
└─UbuntuCrypt-root ext4 ID /
This will give you your partition id’s. Identify your new OS partition Id, and write it down. You want the ID of the luks partition and not of the lvm volume of the partitions within it. I will refer to this ID as LUKS_ID. The ID of the /boot partition will be referred to as BOOT_ID.
Edit the fstab of your new system on /mnt/etc/fstab. Find the entry for the root, and modify accordingly. Also add an entry for /boot
# old entry is commented out, new entry with the same options but different partition is added
# UUID=ID / ext4 errors=remount-ro 0 1
/dev/mapper/UbuntuCrypt-root / ext4 errors=remount-ro 0 1
# boot partition mount
UUID=BOOT_ID /boot ext4 defaults 0 1
if your mount options are different keep them the same, you want to replace UUID=ID with /dev/mapper/UbuntuCrypt-root
edit /mnt/etc/crypttab, if it doesn’t exist create it. This step believe is might not be needed, but I haven’t removed this entry at the time of writing, so I haven’t tested the system without it.
UbuntuCrypt UUID=LUKS_ID none luks,lvm=UbuntuCrypt
LUKS_ID is the id you previously got with the lsblk -f command.
In the old filesystem edit /etc/cryptsetup-initramfs/conf-hook and then copy it over to the new. Uncomment the following line. (https://unix.stackexchange.com/questions/470553/ubuntu-18-04-luks-boot-problems however I did not follow this to the line, since I used my old system’s boot partition to boot for the first time)
CRYPTSETUP=y
rsync -a /etc/cryptsetup-initramfs/conf-hook /mnt/etc/cryptsetup-initramfs/conf-hook sudo update-initramfs -u
This will update our initramfs images with the crypt tools needed to unlock the the root partition before the OS is up and running.
Now we copy the boot files to our new /boot partition.
mount /dev/nvme0n1p2 /mnt/boot rsync -a /boot /mnt/boot
Next we will create some of the partitions we left behind. The others the system will create automatically. (TBH I’m not even sure these two need to be created beforehand.)
mkdir /mnt/proc mkdir /mnt/sys
Now we are going to disable the ubuntu splash screen so we can have a better look of what is happening.
Edit /etc/default/grub and comment out.
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
The important part is quite and splash, these cannot be present.
Now we are going to reboot and edit the grub menu.
Once rebooted and on the grub menu, press e to edit the line you are on. You should be editing the line that normally “you boot from”.
It should originally look something like this
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ID
else
search --no-floppy --fs-uuid --set=root ID
fi
linux /boot/vmlinuz-4.15.0-43-generic root=UUID=ID ro
initrd /boot/initrd.img-4.15.0-43-generic
And we are changing it to something like this.
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root LUKS_ID
else
search --no-floppy --fs-uuid --set=root LUKS_ID
fi
linux /vmlinuz-4.15.0-43-generic root=/dev/mapper/UbuntuCrypt-root ro
initrd /initrd.img-4.15.0-43-generic
In my case the last if else is useless but nonetheless yours might be doing something. Notice how ID has changed to LUKS_ID and where we had root=UUID=ID we now have root=/dev/mapper/UbuntuCrypt-root which is our partition inside the lvm volume, inside the luks partition.
We’ve also changed /boot to just / in vmlinuz and initrd
After these changes are made press f10 and you should start seeing the system booting and midway through it will prompt for a password, that is the password of your luks partition when you first created it.
Once logged in let’s check that we are indeed in our encrypted system.
df -h
df -h
Filesystem Size Used Avail Use% Mounted on
...
/dev/mapper/UbuntuCrypt-root 63G 49G 11G 82% /
...
The important part here is that your / (root) should be the encrypted partition that we previously created in my case UbuntuCrypt-root.
If this the case then we now edit grub config in order to generated our new grub menu which will boot our new system.
make a backup of /boot/efi/EFI/ubuntu/grub.cfg and then edit it.
cp /boot/efi/EFI/ubuntu/grub.cfg /boot/efi/EFI/ubuntu/grub.cfg.bckp
From something like this
search.fs_uuid ID root
set prefix=($root)'/boot/grub'
configfile $prefix/grub.cfg
To what follows.
Notice that we change the ID to our BOOT_ID, which is the UUID of our new boot partition. Also we’ve changed /boot/grub to /grub since our boot partition when on it’s own is now /.
search.fs_uuid BOOT_ID root
set prefix=($root)'/grub'
configfile $prefix/grub.cfg
Now we update all our initramfs images in our /boot partition. And our grub config.
update-initramfs -u -k all update-grub
If you are like me and kept the old system around it will also appear in the grub menu. Remove the partition once you’ve reboot and booted back in to the encrypted / (root) without having to manually change anything.
Once you’ve successfully booted into your system check that you are using the new encrypted system and if so go ahead and delete the partition for the old system.
You have now encrypted your existing Ubuntu installation.