Encrypt an existing Debian system with LUKS
This is how to encyrpt an existing Debian system using LUKS.
In this example the VM (virtual machine) has one virtual disk attached. You will need some megabytes free on your disk.
References
On Internet you can find other posts asking/showing how to encrypt a drive:
- This Reddit post on linuxadmin has some interesting answers.
- A Reddit post on Debian
- A Reddit post on Fedora that says that it works.
- This blog post on education.fr.
- krzys-h's gist to automate the disk conversion.
There was another tool that did the conversion on the fly, named luksipc. I am not sure you should use it.
Actual machine disk disposition
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 2G 0 disk
├─sda1 8:1 0 1.9G 0 part /
├─sda14 8:14 0 3M 0 part
└─sda15 8:15 0 124M 0 part /boot/efi
$ fdisk -l
Disk /dev/sda: 2 GiB, 2147483648 bytes, 4194304 sectors
Disk model: QEMU HARDDISK
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: 56E4EDE3-4BA3-6942-9E58-D1EFDCB32B4A
Device Start End Sectors Size Type
/dev/sda1 262144 4192255 3930112 1.9G Linux root (x86-64)
/dev/sda14 2048 8191 6144 3M BIOS boot
/dev/sda15 8192 262143 253952 124M EFI System
Partition table entries are not in disk order.
$ blkid
/dev/sda15: SEC_TYPE="msdos" UUID="E6F2-C0D9" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="cec893d8-f47d-4f0f-b0b7-c3f3a4fac1cf"
/dev/sda1: UUID="4594baf1-164a-4cb0-980f-105744df462c" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="54c133f2-e7f5-43a6-9540-cea1cbc4654c"
/dev/sda14: PARTUUID="3747106c-99e7-1748-8308-ee6ae31f457b"
Prepare the actual system
apt install cryptsetup cryptsetup-initramfs
Add GRUB_ENABLE_CRYPTODISK=y
to /etc/default/grub
Ensure the keyboard layout is usable in /etc/default/keyboard
XKBMODEL="pc105"
XKBLAYOUT="fr"
XKBVARIANT="latin9"
Run update-initramfs -u
You can check that the cryptsetup is installed: lsinitramfs /boot/initrd.img-6.11.10+bpo-amd64 | grep crypt
Using the filename from the update-initramfs
command.
You may want to reboot
and check that everything still works fine.
Now shut down the machine.
Setup Debian live
- Load
https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-12.9.0-amd64-standard.iso
on a CD or USB stick. - Boot the VM/machine on the ISO.
- Choose the "Live" option.
- Install
cryptsetup
:sudo apt install cryptsetup -y
You will probably need to add the nameserver 1.1.1.1
line to the /etc/resolv.conf
file.
And add an IP manually
- Check before with
ip link
. sudo ip addr add 10.10.10.3/24 dev ens18
.sudo ip net add default via 10.10.10.1
.ping 1.1.1.1
should reply
At this point I installed openssh-server
to work remotely: sudo apt install openssh-server -y
And did allow root access and changed the root password. And restarted the service.
Start converting the drive
Run fdisk -l
and find the drive path.
Now, you can paste the script from krzys-h's gist. Or use my version of this script:
#!/bin/bash
set -euo pipefail
# Uncomment to debug/inspect the commands
#set -x
# Encrypt an existing partition with LUKS2 on Debian 12
# DISCLAIMER: USE AT YOUR OWN RISK AND MAKE BACKUPS
# Made for my personal use and has almost NO error checking!!
# Based on instructions from:
# https://wiki.archlinux.org/index.php/dm-crypt/Device_encryption#Encrypt_an_existing_unencrypted_filesystem
DISK="${1:-}"
if [ -z "$DISK" ]; then
echo "Usage: $0 /dev/sdXY"
exit 1
fi
# Run a filesystem check
e2fsck -f "$DISK"
# Make the filesystem slightly smaller to make space for the LUKS header
BLOCK_SIZE=`dumpe2fs -h $DISK | grep "Block size" | cut -d ':' -f 2 | tr -d ' '`
BLOCK_COUNT=`dumpe2fs -h $DISK | grep "Block count" | cut -d ':' -f 2 | tr -d ' '`
SPACE_TO_FREE=$((1024 * 1024 * 32)) # 16MB should be enough, but add a safety margin
NEW_BLOCK_COUNT=$(($BLOCK_COUNT - $SPACE_TO_FREE / $BLOCK_SIZE))
resize2fs -p "$DISK" "$NEW_BLOCK_COUNT"
# Run the encryption process
# MAN: https://man7.org/linux/man-pages/man8/cryptsetup-reencrypt.8.html
cryptsetup reencrypt --encrypt --reduce-device-size 16M "$DISK"
# Resize the filesystem to fill up the remaining space (i.e. remove the safety margin from earlier)
cryptsetup open "$DISK" recrypt
resize2fs /dev/mapper/recrypt
cryptsetup close recrypt
# Don't forget to update /etc/crypttab and /etc/fstab if required!
#
# For example:
# /etc/crypttab
# crypt_root UUID=xxx none luks
# /etc/fstab
# /dev/mapper/crypt_root / ext4 errors=remount-ro 0 1
#
# Remember to run "update-initramfs -u -k all" after updating the rootfs crypttab
Adjust the encryption key
As said on Debian's reddit and Unix StackExchange GRUB will not unlock if the keyslot is PBKDF: argon2id
You will need to run:
cryptsetup luksDump /dev/sda
to check that is needs to be convertedcryptsetup luksConvertKey --pbkdf pbkdf2 /dev/sda
to convert the keycryptsetup luksDump /dev/sda
to check that is workedsudo cryptsetup --verbose open --test-passphrase /dev/sda
to check the password is working
Note: always use --pbkdf pbkdf2
to change the password or do other key changes.
Example to change the password: cryptsetup luksChangeKey --pbkdf pbkdf2 /dev/sda
Chroot into the system and adjust it
Thank you finnie.org for this part of the tutorial !
DEVICE_NAME="root_crypt"
cryptsetup open /dev/sda1 ${DEVICE_NAME}
mkdir /mnt/${DEVICE_NAME}
mount /dev/mapper/${DEVICE_NAME} /mnt/${DEVICE_NAME}
mount -t proc none /mnt/${DEVICE_NAME}/proc
mount -t sysfs none /mnt/${DEVICE_NAME}/sys
mount --bind /dev /mnt/${DEVICE_NAME}/dev
Enter the chroot: chroot /mnt/${DEVICE_NAME}
Once in the chroot
- run
fdisk -l
and check if you have an EFI partition- If you have one, mount it:
mount /dev/sda15 /boot/efi
- If you have one, mount it:
- run
blkid -o value -s UUID /dev/sda1
and keep the value - edit
/etc/crypttab
and add the following line:root_crypt UUID=<blkid value here> none luks
- Example:
root_crypt UUID=24bfb42b-007d-4777-9889-46d3e016e60b none luks
- Example:
- edit
/etc/fstab
to change the root line- Example:
PARTUUID=54c133f2-e7f5-43a6-9540-cea1cbc4654c / ext4 rw,discard,errors=remount-ro 0 1
Is now/dev/mapper/root_crypt / ext4 rw,discard,errors=remount-ro 0 1
- Example:
- Check that the
/etc/mtab
does not differ from reality:diff -u /etc/mtab /proc/mounts
If it differs (the diff command returns a difference), run:cat /proc/mounts >/etc/mtab
Fix the boot process
- Re-install grub
grub-install /dev/sda
(I am not sure this step is required) - Update initramfs:
update-initramfs -k all -u
- Run
lsblk -o uuid,name
24bfb42b-007d-4777-9889-46d3e016e60b ├─sda1
4594baf1-164a-4cb0-980f-105744df462c │ └─root_crypt
In /etc/default/grub
edit GRUB_CMDLINE_LINUX=
- Add
cryptdevice=UUID=<your_encrypted_crypt_device_uuid>:root_crypt root=UUID=<your_unencrypted_root_partition_uuid>
- Example
cryptdevice=UUID=24bfb42b-007d-4777-9889-46d3e016e60b:root_crypt root=UUID=4594baf1-164a-4cb0-980f-105744df462c
- Example (should work)
cryptdevice=UUID=24bfb42b-007d-4777-9889-46d3e016e60b:root_crypt root=/dev/mapper/root_crypt
- Example
- Check that it boots on
root=
and hascryptdevice=
by runningcat /boot/grub/grub.cfg | grep -F "root="
- Run
update-grub
- Check that it boots on
root=
and hascryptdevice=
by runningcat /boot/grub/grub.cfg | grep -F "root="
You can learn more about the boot parameters on the wiki page of Archlinux.
Exit the chroot: exit
Cleanup the chroot
umount /mnt/${DEVICE_NAME}/proc
umount /mnt/${DEVICE_NAME}/sys
umount /mnt/${DEVICE_NAME}/dev
umount /mnt/${DEVICE_NAME}/boot/efi
umount /mnt/${DEVICE_NAME}
cryptsetup close ${DEVICE_NAME}
rmdir -v /mnt/${DEVICE_NAME}
Finishing the job
Shutdown the live VM: poweroff
And boot the machine to see if it works ?!
If the system hangs on random: crng init done
then the unlock may be waiting for you on another TTY.
Explained on RaspberryPi StackExchange.
Bonus commands: grow the LUKS partition and the ext4 partition to the full disk size
Thank you to foorschtbar (blog post on fotto.de) for the commands.
If you resize your VM disk, you may want to expand. This also works to do a live resizing of the root partition.
$ apt install -y parted
$ parted /dev/sda
GNU Parted 3.5
Using /dev/sda
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 53.7GB
Partition Table: gpt
Number Start End Size File system Name Flags
14 1049kB 4194kB 3146kB bios_grub
15 4194kB 134MB 130MB fat16 boot, esp
1 134MB 2146MB 2012MB
(parted) resizepart
Partition number? 1
End? [2146MB]? 100%
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 53.7GB
Partition Table: gpt
Number Start End Size File system Name Flags
14 1049kB 4194kB 3146kB bios_grub
15 4194kB 134MB 130MB fat16 boot, esp
1 134MB 53.7GB 53.6GB
(parted) q
If you use LVM, use the blog post linked above.
# I assume the LUKS partition is open at the name root_crypt
cryptsetup resize root_crypt
# Resize the EXT-4 file system
resize2fs /dev/mapper/root_crypt
- Reboot, all done.