When it comes to block device encryption on Linux, dm-crypt
in combination
with a LUKS header is
the de facto standard.
While the setup procedure is well documented in the arch wiki, I couldn't find a straightforward explanation on how to move an existing installation to an encrypted partition. Here is what I did to save me the trouble of reinstalling and setting up my system.
Threat model
Let's be clear, disk encryption is not a silver bullet against every possible kind of attack. In particular, as the arch wiki mentions, you will still be vulnerable to:
-
Attackers who can break into your system after you have already unlocked the encrypted parts of the disk.
-
Attackers who are able to gain physical access to the computer while it is running, or very shortly after it was running, if they have the resources to perform a cold boot attack
-
Rubber-hose cryptanalysis. Also, see XKCD #538
My thread-model though is quite simple in this case: I will be using this drive in a notebook and carrying it around a lot. I might lose it or have it stolen by random thieves. If they are able to perform any of the attacks above, I'm sure they will also be able to force me to give them the key, so I won't bother considering those. The setup above should be good enough, that I will be quietly weeping over my trusty X230 instead of the private data on the drive, if forget it on the train.
Prerequisites
You will need a few basics. I moved the installation to a new SSD of the same size and used a SATA to USB adapter to connect them both at once.
- The new drive
- SATA-USB adapter
- Bootable live media, I used the arch install USB
- A working installation
I'll also assume you have a backup of your data, since you could easily lose it if something goes wrong (you should have those anyway).
Create the partitions
My setup has only two partitions: a small EFI partition (/boot
) and the root
file system (/
). You can get this information e.g. form fdisk
, using p
to
print the partitions.
Disk /dev/sda: 223.58 GiB, 240057409536 bytes, 468862128 sectors
Disk model: KINGSTON SA400S3
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: BF841FB1-0634-4826-A240-2D70832E3D5C
Device Start End Sectors Size Type
/dev/sda1 2048 1128447 1126400 550M EFI System
/dev/sda2 1128448 468860927 467732480 223G Linux filesystem
There are valid reasons to encrypt the /boot
, but it makes the setup more
complicated and not necessary for what I want to accomplish. My goah is to
encrypt /
, which especially also contains my /home
folder with private
data. The bootloader will remain installed in the unencrypted /boot
partition
and unlock the encrypted partition on boot.
Armed with this information you can plug in the drive using the adapter and
recreate the partition table like you would normally. I won't go into detail on
how to create the
partitions, as there is
nothing special it, the encryption step comes later. I used gparted
, also
don't forget to set the boot
and esp
flags for the boot partition and set
the correct filesystem types.
Setup encryption
At this point you can boot into your previously created live media. I'll assume
in the following, that the existing (unencrypted) installation is located on
your internal drive /dev/sda
and the new, to be encrypted drive is located at
/dev/sdb
. This is the right moment to create the filesystem on your new
/boot
drive.
While the /boot
partition (/dev/sdb1
) requires nothing else for
now, we now need to set up the encryption on the new root partition at
/dev/sdb2
.
Using cryptsetup
we initialize the LUKS partition and set the initial
passphrase on key-slot 0. LUKS allows for multiple key-slots, which may be used
for other forms of authentication, e.g. a hardware security token. The following
initializes the LUKS partition, unlocks it and creates an ext4 filesystem inside.
Before continuing it might be a good idea to verify that everything went well and the LUKS partition works as expected. You should be able to close and re-open it, we will try mounting it in the next step too.
Copy the data
We will now mount everything and copy over the data. Assuming you are booted
into a live media and have all necessary privileges create two folders: one for
the "old" drive (/dev/sda
) and one for the "new" one (/dev/sdb
). It wont
matter where you create them as they are ephemeral. For simplicity, I created two
folders in the root home directory.
You can mount the existing installation to /root/old_rootfs
. This also
includes mounting the /boot
partition located on /dev/sda
inside the
mounted root filesystem of the old drive.
You can mount the new, encrypted, drive in the same manner, the only difference
being that you will mount /dev/mapper/cryptroot
instead of mounting
/dev/sdb2
directly.
While you could have copied the partitions one after the other, with the setup
above you now only have to copy everything from /root/old_rootfs
to
/root/new_rootfs
, taking care to preserve file attributes.
The rsync
command should be available or can be easily installed on most
platforms and will do the job nicely. Adding the --info=progress2
flag, gives
an estimate of the total progress instead of the single files being copied.
Watch out for the slashes in the command though, as rsync
will copy the folder
itself instead of the contents if you omit them.
Depending on the amount of used storage this might take a while. Let it run
until it finishes. When it's finished, /root/new_rootfs
should list the same
contents as /root/old_rootfs
.
At this point, you can unmount the old drive to prevent any mistakes that might mess it up. This is not strictly necessary, but gives you an additional backup in case you want to revert to it or start over. I even went one step further, taking the old drive out physically and rebooting into the live system with only the new drive now build in. If you do so, you will need to mount everything again, also watch out for changed device descriptors.
Congrats, your data is now on an encrypted partition! There are a few more steps to make it boot though.
Chroot into new system
The following steps need to be done from inside the new system. It is not
bootable yet, but we can chroot
(or arch-chroot
on Linux arch) into it. With
both /dev/sdb1
and /dev/sdb2
still mounted, use arch-chroot
.
Execute the rest of these instructions in the chroot.
Configure fstab
Depending on your setup, you might need to update your /etc/fstab
. Using
lsblk -f
you should see something similar to this:
Use the shown UUIDs
to write your /etc/fstab
. Warning: Don't confuse
the UUID
of your root partition itself (e.g. /dev/sda2
) with the UUID
of
the encrypted volume! In my case my /etc/fstab
file looks like this:
UUID=9b2863ce-ed0b-41de-a96e-b02a02f3bada
UUID=A319-9DF9
Once again: Use the UUID
of cryptroot for /
, not the one from
/dev/sda2
!
Configure mkinitcpio
It is now time to configure the kernel to work with the encryption. For this we
need to add some hooks to /etc/mkinitcpio.conf
. There are different hooks that
can be used here, I will be using the default encrypt
hook. For more detailed
information the arch
wiki
is again a great reference.
In particular, we need to add the keyboard
, keymap
and finally the encrypt
hook to HOOKS=(..)
. You can leave out the keymap
hook, if you are you use
the default US keymap. In my case the HOOKS=(...)
in /etc/mkinitcpio.conf
look like this:
HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems keyboard fsck)
After saving the file, regenerate the initramfs with all presets
Config bootloader
The last step is to configure the bootloader. We need to pass this kernel parameter:
cryptdevice=UUID=device-UUID:cryptroot root=/dev/mapper/cryptroot
Note: The device-UUID
is here UUID
of /dev/sdb2
, not the one from the
encrypted volume like before.
For grub this means editing /etc/default/grub
like this:
GRUB_DISTRIBUTOR="Arch"
GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=UUID=424372e4-ac1d-4925-83ba-baa6d5ec6117:cryptroot root=/dev/mapper/cryptroot"
GRUB_CMDLINE_LINUX=
With the file in place, regenerate the grub.cfg
file with:
Reboot
That's it, you're done! If everything went well, you can now reboot into the
system. Before doing so, leave the chroot
, then unmount the partitions for
good measure and throw a sync
in there to be sure everything is written.
At this point your system should reboot into grub and then ask you for a passphrase along the boot process. If you experience problems, it might help to reinstall the bootloader.
I later added my Yubikey to the setup, allowing it to be used to unlock the encrypted volume. I will be detailing how that was done in a separate post.