How to encrypt an existing archlinux LVM installation [LVM on LUKS]
Many users need to secure their laptop, workstation or regular PC, this users want to protect their information. In Linux exist many cryptographic techniques to protect a hard disk, directory and partition, one of this techniques is Linux Unified Key Setup (LUKS) which uses the kernel device mapper subsystem via the dm-crypt module which make the encrypted device transparent to the user.
Assumptions
This tutorial only encrypt an existing LVM installation, the EFI and boot partitions are in a non-encrypted partition. In order to encrypt an existing LVM installation we need to have root permissions and an external temporally drive to allocate the entire volume group.
In this tutorial the system drive is called rootDrive and temporally drive is called tmpDrive, the LVM root partition (partition to encrypt) is called rootDriveXY, the temporally partition is called tmpDriveXY both are formatted as Linux LVM.
The entire system are installed in a single volume group, in this tutorial is called “vg-sys”.
You can realize the entire process without umount any partition because of flexibility of LVM, in summary this process can be do on-the-fly.
Warning
Only realize the process if you know what are you doing a bad execution can result in a system damage and data-loss, i recommend to realize a backup before starting this tutorial.
The specific case
I have an existing archlinux installation on LVM volumes, the entire system is in a single volume group “arch”, I have 5 logical volumes (swap, root, var, home and data) in a single physical volume, the entire disk have 3 partitions EFI (/dev/sdb1), boot (/dev/sdb2) and LVM (/dev/sdb3). In order to encrypt an existing LVM installation (/dev/sdb3) I have an empty temporally hard drive (/dev/sda1) with the minimum size of volume group allocated size, in my case the allocated size is 208 GiB (arch volume group), the temporally drive have 465 GiB (/dev/sda1), the temporally drive is formatted as Linux LVM, this setup is showing in the next image
Steps
The first step is to create a physical volume in temporally drive, extend the “vg-sys” volume group to temporally drive and move volume group to temporally drive.
# create physical volume
$ pvcreate /dev/tmpDriveXY
# extend "vg-sys" to temporally drive
$ vgextend vg-sys /dev/tmpDriveXY
# move volume group to temporally drive
$ pvmove /dev/rootDriveXY /dev/tmpDriveXY
Once the volume group is moved, reduce the rootDriveXY from volume group “vg-sys” and remove the physical drive to be encrypted /dev/rootDriveXY
# remove physical drive from volume group
$ vgreduce vg-sys /dev/rootDriveXY
# remove physical drive
$ pvremove /dev/rootDriveXY
Change the partition type of root drive, on GPT the code is 8309 for Linux LUKS
# change the code of root drive partition
$ gdisk /dev/rootDrive
# change type with t, choose partition number
# set type 8309 for Linux LUKS
# see changes whit p and write with w
$ gdisk -l /dev/rootDrive
Wipe the partition to prevent cryptographic attacks or unwanted file recovery
# create a temporary encrypted container
$ cryptsetup open --type plain -d /dev/urandom /dev/rootDeviceXY to_be_wiped
# verify
$ lsblk
# wipe with zeros, wait til "No space left on device"
# be patient, this step takes a long time
$ dd if=/dev/zero of=/dev/mapper/to_be_wiped bs=1M status=progress
# close wiped device
$ cryptsetup close to_be_wiped
A this point probably you want to check performance of encrypt algorithms, use the next command to run a benchmark
# check algorithm benchmark
$ cryptsetup benchmark
I choose an aes-xts-plain64 cipher with a key size of 256 and sha256 hash. To encrypt the rootDriveXY use the next command
# encrypt device and set passphrase
$ cryptsetup -v --type luks --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-passphrase luksFormat /dev/rootDriveXY
Open encrypted device with passphrase, create a LVM physical volume, extend the “vg-sys” volume to encrypted physical volume and move the temporally drive to encrypted
# open encrypted volume
$ cryptsetup open /dev/rootDriveXY cryptarch
# create a physical LVM device
$ pvcreate /dev/mapper/cryptarch
# extend the "vg-sys" group
$ vgextend vg-sys /dev/mapper/cryptarch
# move volume group to encrypted drive
$ pvmove /dev/tmpDriveXY /dev/mapper/cryptarch
Now remove the temporally drive from LVM
# remove temporally drive from volume group
$ vgreduce vg-sys /dev/tmpDriveXY
# remove physical volume from temporally drive
$ pvremove /dev/tmpDriveXY
Configure mkinitcpio, first edit /etc/mkinitcpio.conf file and change hooks like this
HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck)
Then recreate the initramfs image for linux-lts kernel
$ mkinitcpio -P linux-lts
Configuring the boot loader to unlock the encrypted root partition at boot, the following kernel parameter needs to be set by the boot loader, this can be set in /etc/default/grub
# get UUID of encrypted drive
# in this case /dev/rootDriveXY not /dev/mapper/cryptarch
$ blkid
# add this line in GRUB_CMDLINE_LINUX
cryptdevice=UUID=rootDriveXY-UUID:cryptarch root=/dev/vg-sys/root
# uncoment GRUB_ENABLE_CRYPTODISK="y"
# regenerate grub.cfg file
$ grub-mkconfig -o /boot/grub/grub.cfg
If everything goes fine reboot the system and in boot time the system should ask a password to open the encrypted rootDriveXY as shown in the next image
Finally I recommend to wipe the temporally drive to prevent unwanted data recovery.