Skip to main content

Full disk encryption on Debian Linux with LUKS

Member for

5 months
Submitted by valery on

Winter holidays was a good time to accomplish things that were postponed for too long. One of them was turning full disk encryption on my working laptop.

I'm using Debian Linux, so LUKS (Linux Unified Key Setup) was an obvious choice.

Linux Unified Key Setup (linux.com)

Image courtesy Linux.com

Easiest way to enable full disk encryption is (obviously) during system reinstall, but I spent too much time building comfortable working environment, so I tried (and succeeded - spoilers!) to encrypt existing system.

The process was largely based on the excellent post by William Desportes, but since my experience was slightly different, I decided to publish it here.

Before proceeding

  • Do not use luksipc (LUKS in place conversion) - it’s an outdated tool, and even its author recommends using cryptsetup (part of the package of the same name) on the latest version of package readme
  • Backup important files before proceeding (that part is obvious but never hurts to repeat)

Prepare the target machine

Install necessary packages:

sudo apt install cryptsetup cryptsetup-initramfs

Add the following line to /etc/default/grub:

GRUB_ENABLE_CRYPTODISK=y

Prepare a bootable device

I have taken an Xfce version from Debian Live repo, but you can take any other reasonable modern Live CD image (you can use Ubuntu Live CD for encrypting Debian, or vice versa, or even take RedHat-based image)

Prepare the encrypting script

Save the following script as encryptdrive.sh on another USB stick (Live image is usually read-only) to avoid typing it while in Debian Live:

#!/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

Now boot using the prepared device into live Debian to skip mounting your main filesystem(s)

Steps to perform when booted into Debian Live

Find the partition(s) you want to encrypt:

sudo fdisk -l

On newer laptops with SSDs, disk names will be something like /dev/nvme0, on older ones /dev/sda, /dev/sdb etc.

Start the encryption with encrypdrive.sh saved earlier

For me, it was /dev/nvme0n1p2 (/dev/nvme0n1p1 reserved for EFI partition). From now on, let’s assume this is the case for you too. If your main partition is different, just replace the device name accordingly)

sudo /bin/bash encryptdrive.sh /dev/nvme0n1p2

This will take some time, depending on the speed of your system and disk size

Important: convert the drive into LUKS1 format

GRUB doesn’t support LUKS2 format well enough, so better stick to safer version.
These operations are much faster than encryption itself, since they change only encryption header.

sudo cryptsetup luksConvertKey --pbkdf pbkdf2 /dev/nvme0n1p2
sudo cryptsetup convert --type luks1 /dev/nvme0n1p2

Adjust boot settings in the encrypted drive:

export DEVICE_NAME="root_crypt"
cryptsetup open /dev/nvme0n1p2 ${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/${DEVIC-bind /dev /mnt/${DEVICE_NAME}/dev

Chroot to encrypted drive

chroot /mnt/${DEVICE_NAME}

Steps to perform in chroot-ed environment

  • If you have an EFI partition (/boot/efi), mount it: mount /dev/nvme0n1p1 /boot/efi (check device name with sudo fdisk -l
  • run blkid -o value -s UUID /dev/nvme0n1p2 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
  • Re-install grub sudo grub-install /dev/nvme0 (Like William, I am not sure this step is required)
  • Update initramfs: sudo update-initramfs -k all -u
  • Update boot loader with sudo update-grub
  • Exit the chroot with exit

Final cleanup

sudo umount /mnt/${DEVICE_NAME}/proc
sudo umount /mnt/${DEVICE_NAME}/sys
sudo umount /mnt/${DEVICE_NAME}/dev
sudo umount /mnt/${DEVICE_NAME}/boot/efi
sudo umount /mnt/${DEVICE_NAME}
sudo cryptsetup close ${DEVICE_NAME}
sudo rmdir -v /mnt/${DEVICE_NAME}

That should be it. You should be ready to reboot into more secure environment.
Enjoy!