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.isoon 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.1should 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/sdato check that is needs to be convertedcryptsetup luksConvertKey --pbkdf pbkdf2 /dev/sdato convert the keycryptsetup luksDump /dev/sdato check that is workedsudo cryptsetup --verbose open --test-passphrase /dev/sdato 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 -land 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/sda1and keep the value - edit
/etc/crypttaband 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/fstabto change the root line- Example:
PARTUUID=54c133f2-e7f5-43a6-9540-cea1cbc4654c / ext4 rw,discard,errors=remount-ro 0 1Is now/dev/mapper/root_crypt / ext4 rw,discard,errors=remount-ro 0 1
- Example:
- Check that the
/etc/mtabdoes not differ from reality:diff -u /etc/mtab /proc/mountsIf 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,name24bfb42b-007d-4777-9889-46d3e016e60b ├─sda14594baf1-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.