Unlocking LUKS-encrypted drives at boot
You can use Revaulter to protect the encryption key for a LUKS volume. Instead of storing the key on disk or typing a passphrase at the console, a script calls revaulter-cli during boot and an admin approves the unlock from their phone.
Setup#
Generate a random key and encrypt the LUKS volume with it:
dd if=/dev/urandom bs=32 count=1 | base64 > /tmp/disk-key.txt cryptsetup luksFormat /dev/sdX --key-file /tmp/disk-key.txtWrap the key with Revaulter:
revaulter-cli encrypt \ --server https://revaulter.example.com \ --request-key AbCdEf0123456789GhIj \ --key-label boot-disk \ --algorithm A256GCM \ --input /tmp/disk-key.txtApprove the request in the Revaulter web UI. The CLI outputs a JSON envelope with the ciphertext, nonce, and tag. Save this output (for example, in
/etc/revaulter/boot-disk.json).Securely delete the plaintext key:
shred -u /tmp/disk-key.txt
Boot script#
Create a script that runs early in the boot process (e.g. a systemd unit that runs before the mount target):
#!/usr/bin/env bash
set -euo pipefail
REVAULTER_SERVER="https://revaulter.example.com"
REQUEST_KEY="AbCdEf0123456789GhIj"
KEY_LABEL="boot-disk"
WRAPPED_KEY="/etc/revaulter/boot-disk.json"
# Read the wrapped key components
CIPHERTEXT=$(jq -r '.value' "$WRAPPED_KEY")
NONCE=$(jq -r '.nonce' "$WRAPPED_KEY")
TAG=$(jq -r '.tag' "$WRAPPED_KEY")
# Ask Revaulter to decrypt — an admin must approve from their browser
PLAINTEXT_KEY=$(revaulter-cli decrypt \
--server "$REVAULTER_SERVER" \
--request-key "$REQUEST_KEY" \
--key-label "$KEY_LABEL" \
--algorithm A256GCM \
--value "$CIPHERTEXT" \
--nonce "$NONCE" \
--tag "$TAG" \
--format raw \
--note "boot unlock" \
--timeout 10m)
# Unlock the LUKS volume
echo -n "$PLAINTEXT_KEY" | cryptsetup luksOpen /dev/sdX encrypted-root --key-file=-
# Clear the variable
unset PLAINTEXT_KEYWhen the server boots, it pauses at this script and sends a webhook notification. The admin opens Revaulter on their phone, authenticates with their passkey, and approves the unlock. The disk key is decrypted in the admin’s browser, returned to the CLI, and piped directly into cryptsetup — it never touches disk.
systemd unit (optional)#
[Unit]
Description=Unlock encrypted root via Revaulter
DefaultDependencies=no
Before=local-fs.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/revaulter-unlock.sh
RemainAfterExit=yes
[Install]
WantedBy=local-fs.target