Full-disk encryption on a remote VPS, with remote unlock
LUKS2 on a remote server with dropbear-initramfs unlock: the argon2id parameters that matter, and the limitations nobody mentions until you hit them.
How do I encrypt a VPS disk so the hosting provider cannot read it?
Full-disk encryption on a remote server has an obvious problem: nobody is standing at the console to type the passphrase. The standard answer is dropbear-initramfs, a tiny SSH server embedded in the initial ramdisk that lets you supply the key over the network before the root filesystem is mounted.
This is well-trodden ground and it works. What follows is the version we deploy, and — more usefully — an honest account of what it does not do.
What this actually protects against
Be precise, because vendors are routinely not:
| Threat | Protected? |
|---|---|
| Drive removed from the rack and imaged | Yes |
| Provider compelled to hand over the volume | Yes — they hand over ciphertext |
| Decommissioned drive resold or improperly wiped | Yes |
| Snapshot taken while the machine is powered off | Yes |
| Snapshot taken while the machine is running | No — the key is in memory |
| Hypervisor operator dumping guest memory | No |
| Live root compromise of the guest | No |
| Network traffic interception | No — that is TLS's job |
The pattern: FDE protects data at rest on hardware that is not currently running your workload. That is a narrower guarantee than "the provider cannot read my data," but it is the guarantee that covers seizure, which is the scenario that actually happens.
Partition layout
A minimal, well-understood layout:
/dev/vda1 512M ext4 /boot (unencrypted — kernel + initramfs)
/dev/vda2 rest LUKS2 → cryptroot (everything else)
└── ext4 or btrfs mounted at /
/boot must be readable by the bootloader, so it is unencrypted. This is a real exposure: an attacker with physical access could modify the kernel or the initramfs to capture your passphrase — the classic "evil maid" attack. Secure Boot with your own keys mitigates it; on most VPS platforms that is not available, so treat /boot as trusted-but-verifiable and check its hashes if the machine was ever powered down outside your control.
Creating the container
cryptsetup luksFormat \
--type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--iter-time 5000 \
/dev/vda2
The parameters that matter:
--pbkdf argon2id— memory-hard key derivation. This is the single most important flag. PBKDF2, the LUKS1 default, is cheap to attack with GPUs; argon2id is not, because it forces the attacker to allocate memory per guess.--pbkdf-memory 1048576— 1 GiB per derivation attempt, and the number you must size to the machine. The derivation runs inside the initramfs, so if the instance does not have the memory free, unlock fails and you are booting rescue media. On a 2 GB instance use 524288 (512 MiB); 1 GiB is the right value from 4 GB upwards. Our own provisioning picks the parameter from plan RAM for exactly this reason.--key-size 512— with XTS this yields AES-256, since XTS splits the key in half.
Generate the passphrase on your own machine with a real generator — diceware, or openssl rand -base64 32. Never let the provider generate it, and never transmit it over anything but the pre-boot SSH session itself.
Remote unlock with dropbear
apt install dropbear-initramfs cryptsetup-initramfs
# your public key, pre-boot only — use a key you do not use elsewhere
echo 'ssh-ed25519 AAAA...' > /etc/dropbear/initramfs/authorized_keys
chmod 600 /etc/dropbear/initramfs/authorized_keys
# distinct port so your client does not warn about a changed host key
echo 'DROPBEAR_OPTIONS="-p 2222 -s -j -k -I 180"' \
>> /etc/dropbear/initramfs/dropbear.conf
# static network in the pre-boot environment
echo 'IP=192.0.2.42::192.0.2.1:255.255.255.0::eth0:off' \
>> /etc/initramfs-tools/initramfs.conf
update-initramfs -u -k all
Then, after a reboot:
# 192.0.2.x below is an RFC 5737 documentation address — substitute your own
ssh -p 2222 [email protected]
# cryptroot-unlock
Please unlock disk cryptroot: ********
Boot continues and the real SSH daemon comes up on port 22 with a different host key. Pin both in your ~/.ssh/known_hosts so a substituted pre-boot environment is detectable.
The -I 180 flag idles the pre-boot dropbear out after three minutes, which limits how long that surface is exposed if you do not connect.
Header backup and key management
The LUKS2 header holds the key slots. If it is corrupted, your data is gone — the ciphertext is intact and permanently unreadable. Back it up before you put anything on the volume:
cryptsetup luksHeaderBackup /dev/vda2 \
--header-backup-file luks-header-$(hostname).img
Store that file somewhere that is not the server, and treat it as sensitive: it contains the key slots, so anyone with the header and your passphrase can decrypt the volume.
Add a second key slot with an independently stored recovery passphrase. LUKS2 supports up to 32 key slots — it is LUKS1 that was limited to 8 — so there is no reason to design around a tight budget. Using exactly one slot is how people lose data.
Limitations you must accept
- Unattended reboots do not come back. A kernel panic at 3 a.m. leaves the machine sitting at a passphrase prompt until you wake up. This is the intended behaviour and it is the main operational cost. Some people mitigate it with a network-bound key (clevis/tang) held in a second jurisdiction, which trades some of the security property for availability.
- The key is in RAM while running. Anything that can read guest memory can extract it. See our RAM-only article for the case where that matters most.
- /boot is unencrypted. Verify its hashes after any powered-down period you did not control.
- A broken initramfs locks you out. Always keep out-of-band console access available so you can boot rescue media. Test the unlock path before you put data on the machine — reboot deliberately, at least twice.
On VPSDEN, zero-knowledge LUKS is configured this way by default on every disk-backed plan, at no charge. We never receive the passphrase, and the out-of-band console is included so a bad initramfs is recoverable.