#!/usr/bin/env bash # Untested as a whole, tested as parts as of 2026-02-22 # This is written with red hat in mind (dracut). # Adapting to debian should be a trivial exercise. # # Boils down to: # 1. Generate an arbitrary keyfile # 2. Insert this key into the luks header block # 3. Tell your initramfs to include said keyfile # 4. Tell crypttab to look for this file as a key # 5. Regenerate the initramfs and inspect it set -euo pipefail echo "Have you read the script? READ IT and understand it." read -r -p "Type 'YES' to continue: " RESPONSE [[ "${RESPONSE}" == "YES" ]] || { echo "Aborted." exit 1 } KEYFILE="/etc/keyfile" DEVICE="" if [ -z "${DEVICE}" ]; then echo "DEVICE variable is not set" exit 1 fi if ! cryptsetup isLuks "${DEVICE}" >/dev/null 2>&1; then echo "${DEVICE} is not a LUKS device" exit 1 fi # Generate the keyfile openssl rand -out ${KEYFILE} 4096 chmod -v 0400 ${KEYFILE} chmod -v root:root ${KEYFILE} # Add the keyfile to the luks partition cryptsetup luksAddKey ${DEVICE} ${KEYFILE} # Make sure the new key is included (should be at least two keys now) cryptsetup luksDump ${DEVICE} # Add the keyfile path to where it says 'none', and optionally append the keyfile-timeout=10s to the parameters # luks-blah UUID=blah ${KEYFILE} discard,keyfile-timeout=10s # Backup, of course TIMESTAMP="$(date +%s)" cp /etc/crypttab /root/crypttab_bak_${TIMESTAMP} # Do the required substitutions with some awk magic awk '{ key=$3 options=$4 if (key=="none") key="/etc/key" if (options !~ /keyfile-timeout=/) options = options ",keyfile-timeout=30s" print $1, $2, key, options }' /etc/crypttab diff --color=always -u /root/crypttab_bak_${TIMESTAMP} /etc/crypttab # Tell dracut to include our key in the initramfs cat </etc/dracut.conf.d/copy-keyfile.conf install_items+=${KEYFILE} EOF # Regenerate initramfs so that it includes our keyfile dracut -f lsinitrd | grep ${KEYFILE:1} echo "If your keyfile got printed above, all should be fine."