All systems operational Amsterdam · Paris · Reykjavík +5 Pay with Cryptocurrency
Security & hardeningAdvanced18 min readUpdated 2026-08-29

Encrypt a VPS with LUKS

Full-disk encryption answers exactly one question: what happens when somebody else ends up holding your disk while it is powered off. Here is how to set it up properly on a rented VPS — and an honest account of the threats it does not touch.

Encrypt a VPS with LUKS
On this page
  1. What encryption at rest actually protects
  2. The rented-hardware caveat, stated plainly
  3. Data volume or root filesystem: pick before you type
  4. What you need before you start
  5. Step-by-step
  6. Keyslots, headers and the passphrase you rotated
  7. Performance: AES-NI, NVMe and the two flags worth knowing
  8. The root filesystem route, and remote unlock over SSH
  9. Day two: what changes, and what does not
  10. Frequently asked questions

The case for encrypting a server you rent is narrower than the marketing suggests, and much stronger inside that narrow scope. NVMe drives fail and go back to a vendor with your data still on them. Nodes get decommissioned and the storage resold. Hardware gets imaged, or carried out of a rack. In every one of those, LUKS is the difference between a readable filesystem — your keys, your database, your mail spool — and a block of noise nobody can do anything with.

What it is not is protection from the machine you are running on. That distinction is the whole guide, so it comes first, before a single command. Then the work: a LUKS2 volume done correctly, a header backup, encrypted swap, remote unlock over SSH, and the recovery plan for the reboot that does not come back. The box underneath you can rent without ID and pay for in Monero; encryption is a layer you add on top of that, not a substitute for it.

What encryption at rest actually protects

Full-disk encryption answers one question and answers it completely: what happens when someone else ends up holding the disk while it is powered off? On rented infrastructure that is not hypothetical. Drives fail and go back to the supplier. Nodes are retired and their storage resold. Volumes get imaged during an investigation, or leave a building in a crate.

  • Covered. A powered-off disk, an offline image of your volume, a drive returned under warranty, a decommissioned node, a copied snapshot file. In each case the attacker holds ciphertext and a header, and without a passphrase that is the end of the story.
  • Not covered: a running machine. The moment the volume is open, the key is in kernel memory and the filesystem is plain to anything with root.
  • Not covered: your traffic. Bytes on the wire are TLS and WireGuard's problem. LUKS never sees them.
  • Not covered: a compromised root account. An intruder who is already inside reads your files through the same mount you do. That is what hardening is for, and the two controls are not interchangeable.

The list is short deliberately. Encryption at rest is a cheap, high-value control with a precisely bounded scope, and almost all the disappointment people report with it comes from having quietly expected it to cover the other three lines too.

The rented-hardware caveat, stated plainly

When your encrypted volume is open, the key is in the guest's RAM — and on any VPS anywhere, that RAM lives on a machine the operator physically controls. A hypervisor can read guest memory. This is not a flaw in LUKS, or in KVM, or in this host in particular; it is what renting a computer means, and any provider telling you otherwise is describing a product that does not exist.

So the accounting is blunt: encryption at rest takes the offline attack to impossible and leaves the online attack exactly where it was. A drive that leaves the rack becomes worthless. A running server is as exposed as it was yesterday. Both halves of that sentence are true at once, and a guide that only tells you the first half is not doing you a favour.

What moves the second needle is a different set of controls, and they stack with encryption rather than replacing it. There is nothing on file to disclose, because signup here is no-KYC — an email for credential delivery and nothing else. The payment is settled on chain rather than through a bank. And the jurisdiction the box sits in decides which orders compel anything at all. Our honest breakdown of what a crypto-paid VPS hides works through the rest, and the Fourteen Eyes entry covers the intelligence-sharing side. Read as one layer among several, LUKS is excellent value. Read as a shield against your own host, it is a misunderstanding.

Data volume or root filesystem: pick before you type

There are two shapes this can take, and the choice is about risk, not about strength.

  • An encrypted data volume. A LUKS container beside the operating system. Everything that matters — databases, mail, keys, uploads, backups — lives inside it; the OS itself stays in the clear. Ten minutes of work, no boot risk at all, and reversible at any point. This is what most readers should build, and it is what the steps below do.
  • An encrypted root filesystem. Everything is inside, including logs, package lists and the shell history you forgot about. Strictly stronger, and genuinely harder to get onto a machine that is already running.

The reason for that difficulty is worth stating because no tutorial ever does: you cannot encrypt a filesystem that is currently mounted read-write and serving your SSH session. Both real methods — shrink-and-copy, or cryptsetup reencrypt in place — need the root offline. On a machine with an out-of-band console you boot an installer and it is routine. On a headless VPS you are pivoting the running system into a RAM disk first, and if any part of that goes wrong the box does not come back and the recovery path is a reinstall, which wipes the disk.

So: build the data volume today, put everything of consequence on it, and treat an encrypted root as a decision you make at deploy time on a machine with nothing to lose yet. The last section covers that route, including dropbear-initramfs for typing the passphrase over SSH at boot.

What you need before you start

Not much, which is part of why this is worth doing.

  • A plan. Encryption adds no RAM requirement and almost no CPU. Cub (1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo) is enough; Scout (2 vCPU / 4 GB / 70 GB, $9.00/mo) is the comfortable size if the box also runs a real service. The one number that matters is disk, because your encrypted volume comes out of it.
  • Debian 12 or 13 from the template library, or Ubuntu LTS — the commands below are Debian-flavoured and the package names differ elsewhere. Deploy takes about a minute and full KVM virtualisation means a real kernel with the dm-crypt modules present, not a container borrowing someone else's.
  • Ten minutes of basic hardening first. Encryption on a box that still accepts password logins is a lock on a door with no frame.
  • A passphrase you have not used anywhere else, generated rather than invented, and stored somewhere that survives you losing this machine. There is no recovery, no reset and no support ticket that helps.
  • Somewhere off the box to keep the header backup. Weekly snapshots are included on every plan, but a snapshot of an encrypted volume is still encrypted — useful for rollback, useless if the passphrase is gone.

Location makes no difference to any of this, so choose on price or jurisdiction: Amsterdam, Paris, Bucharest and Sofia sit at base price, while Zurich, Reykjavik, Stockholm and Kuala Lumpur carry a multiplier.

Step-by-step

  1. Deploy, harden, and confirm the CPU has AES-NI

    Deploy Debian 13 from the template library and spend ten minutes on the basics first: SSH keys only, root password login disabled, nftables default-deny, unattended security upgrades. Then confirm the hardware will not make you pay for this:

    grep -o -m1 ' aes ' /proc/cpuinfo
    apt update && apt install -y cryptsetup
    cryptsetup benchmark

    You are looking for aes-xts figures in the gigabytes per second. Any x86-64 server CPU of the last decade has AES-NI, so encryption will not be your bottleneck — the NVMe underneath it will be, exactly as it was before.

  2. Carve out the space for the volume

    If your plan's disk has unpartitioned space, use it — a real partition is the cleanest thing to encrypt:

    lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
    sgdisk -n 0:0:0 -c 0:secure /dev/vda
    partprobe /dev/vda

    If the template filled the disk, do not fight it. A file-backed container is a first-class citizen here, costs nothing in throughput on NVMe, and can be grown later:

    fallocate -l 20G /var/lib/secure.img
    chmod 600 /var/lib/secure.img
    losetup --find --show /var/lib/secure.img

    Note the loop device it prints — usually /dev/loop0. Everywhere below reads /dev/disk/by-partlabel/secure; substitute your loop device if you took the container route.

  3. Format it as LUKS2 — and cap the memory cost

    This is the command that decides everything, so it is worth reading rather than pasting:

    cryptsetup luksFormat --type luks2 \
      --cipher aes-xts-plain64 --key-size 512 \
      --pbkdf argon2id --pbkdf-memory 262144 --iter-time 5000 \
      /dev/disk/by-partlabel/secure

    --key-size 512 is AES-256 in XTS mode, which splits the key in two — it is not AES-512, which does not exist. --pbkdf argon2id is the memory-hard key derivation that makes brute-forcing your passphrase expensive in RAM as well as CPU.

    --pbkdf-memory 262144 caps that at 256 MB, and it is the line people leave out and regret. Left alone, cryptsetup tunes the memory cost to the RAM available at format time. Unlock the same header later somewhere with less — a 1 GB plan, a rescue environment, an initramfs — and it can fail outright. Cap it deliberately.

  4. Open it, put a filesystem on it, mount it
    cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue \
      --allow-discards open /dev/disk/by-partlabel/secure secure
    
    mkfs.ext4 -L secure /dev/mapper/secure
    mkdir -p /srv/secure
    mount -o noatime /dev/mapper/secure /srv/secure
    df -h /srv/secure

    The two workqueue flags matter on NVMe and nowhere else; --allow-discards keeps TRIM working at the cost of revealing which blocks are in use to anyone holding the powered-off disk. Both are discussed below — the defaults above are the right ones for a general-purpose server.

  5. Back up the LUKS header, off the box

    Do this now, before there is anything on the volume worth losing. The header is roughly 16 MB of metadata holding the keyslots, and a corrupted header means the ciphertext is unrecoverable no matter how well you remember the passphrase:

    cryptsetup luksHeaderBackup /dev/disk/by-partlabel/secure \
      --header-backup-file /root/secure-header.img
    sha256sum /root/secure-header.img

    Copy it somewhere else — scp it down, put it in a password manager, print the hash — then delete the local copy. Treat that file as equivalent to the passphrase, because combined with any passphrase it has ever held, it is.

  6. Move what matters onto the volume

    An encrypted volume nothing writes to protects nothing. Stop the service first, move its state, then bind-mount the old path so nothing else needs reconfiguring:

    systemctl stop postgresql
    rsync -aHAX --info=progress2 /var/lib/postgresql/ /srv/secure/postgresql/
    mv /var/lib/postgresql /var/lib/postgresql.old
    mkdir /var/lib/postgresql
    echo '/srv/secure/postgresql /var/lib/postgresql none bind 0 0' >> /etc/fstab
    mount /var/lib/postgresql
    systemctl start postgresql

    Verify the service is healthy before shred-ing or removing the .old directory — and remember that on a copy-on-write filesystem or an NVMe with wear levelling, deleting the plaintext is not the same as destroying it. The clean version of this story is to create the encrypted volume before the service exists.

  7. Decide how it unlocks, and be honest about it

    Here is the fork everyone hits. Add the volume to /etc/crypttab with noauto so nothing blocks the boot, and unlock it by hand over SSH when you need it:

    echo 'secure /dev/disk/by-partlabel/secure none \
      luks,noauto,discard,no-read-workqueue,no-write-workqueue' >> /etc/crypttab
    cryptdisks_start secure

    That is the honest configuration: the key exists only while you are present, and a reboot leaves the volume shut until you say otherwise. The cost is that unattended reboots come back with the service down.

    The alternative is a keyfile in /etc/crypttab so the volume opens automatically. If that keyfile lives on the same disk, you have not encrypted anything — whoever holds the powered-off drive holds the key next to the lock. It is only meaningful when the key comes from somewhere the disk does not: fetched over a WireGuard tunnel at boot, or typed into an initramfs over SSH as in the last section. Choose deliberately; the default of manual unlock is the one that means what it says.

  8. Encrypt the swap, and verify the whole thing

    Swap is where memory goes to become a disk artefact, so an encrypted volume beside a plaintext swap leaks exactly the secrets you were protecting. A random key per boot is the correct answer — nothing to manage, nothing to lose. Check swapon --show first and substitute your own device; if the template gave you a swap file rather than a partition, delete it and use a small partition instead, because a random-key device needs a block device:

    swapoff -a
    sed -i '/swap/s/^/#/' /etc/fstab
    echo 'swap /dev/vda3 /dev/urandom \
      swap,cipher=aes-xts-plain64,size=512' >> /etc/crypttab
    echo '/dev/mapper/swap none swap sw 0 0' >> /etc/fstab

    Then reboot — while it is still cheap to get wrong — and check the result honestly:

    lsblk -o NAME,FSTYPE,MOUNTPOINT
    cryptsetup status secure
    blkid /dev/disk/by-partlabel/secure   # should say crypto_LUKS
    swapon --show                          # should show /dev/mapper/swap

    The test that counts: with the volume closed, confirm /srv/secure is empty and the service that depends on it refuses to start. If both are true, the encryption is real rather than decorative.

Keyslots, headers and the passphrase you rotated

LUKS2 keeps up to 32 keyslots. Each holds a copy of the same master key, wrapped with a different passphrase, which is why you can add a second passphrase without re-encrypting anything:

cryptsetup luksAddKey /dev/disk/by-partlabel/secure
cryptsetup luksDump /dev/disk/by-partlabel/secure | grep -A2 '^Keyslots'
cryptsetup luksKillSlot /dev/disk/by-partlabel/secure 1

Two passphrases from the start is the right default: one you use, one written down and stored somewhere else. Losing sole access to a volume because of a typo in a password manager is the single most common way people lose LUKS data, well ahead of anything an adversary does.

Now the trap. A header backup taken before you rotated a passphrase still opens the volume with the old passphrase. Keyslots live in the header, so an old copy of the header is an old copy of the keyslots — the master key underneath never changed. If you rotate because a passphrase may have leaked, you must destroy every header backup taken before the rotation and take a fresh one. Otherwise the rotation accomplished nothing except making you feel better.

The same fact makes header backups sensitive in their own right: that 16 MB file plus any passphrase it ever knew is enough to decrypt the volume. Store it where you would store the passphrase, not where you store your snapshots.

Performance: AES-NI, NVMe and the two flags worth knowing

cryptsetup benchmark tells you the truth for your specific vCPU in about fifteen seconds. On any CPU with AES-NI — which means any x86-64 server processor of the last decade — expect several gigabytes per second for aes-xts, comfortably faster than the NVMe underneath it. The practical overhead on real workloads is low single-digit percent, and it is CPU, not latency.

Two cryptsetup options matter on fast storage, and only on fast storage:

cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue \
  --allow-discards open /dev/disk/by-partlabel/secure secure

The workqueue flags bypass dm-crypt's internal queues and hand I/O straight to the device. On a spinning disk they change nothing; on NVMe RAID10 they remove a real bottleneck at high queue depth. Add them to the crypttab options line as no-read-workqueue,no-write-workqueue to make them permanent.

--allow-discards is the one with a trade-off. It passes TRIM through to the NVMe, which keeps write performance up over time — and it also reveals to anyone holding the powered-off disk which blocks are in use and which are free. That is a genuine, if modest, information leak: it exposes roughly how full the volume is and can hint at filesystem structure. On a general-purpose server, take the performance. If the volume's contents are the kind of thing where its size is sensitive, leave discards off.

The root filesystem route, and remote unlock over SSH

If you want everything encrypted, do it on a machine that has nothing on it yet — deploy, convert, then build. The conversion itself is standard: shrink the root filesystem while it is offline, create a LUKS2 container in the freed space, copy the system across with rsync -aHAX, point /etc/fstab and /etc/crypttab at the mapper device, then update-initramfs -u -k all and reinstall GRUB. The part that makes it a headless-VPS problem is the words while it is offline: getting there without a console means pivoting the running system into a RAM root first, and that is the step that ends in a reinstall when it goes wrong.

What makes an encrypted root usable at all on a remote machine is dropbear-initramfs — a roughly 200 KB SSH server baked into the boot image, listening while the kernel waits for the passphrase:

apt install dropbear-initramfs cryptsetup-initramfs

# Debian 12/13: /etc/dropbear/initramfs/
cp ~/.ssh/unlock_key.pub /etc/dropbear/initramfs/authorized_keys
chmod 600 /etc/dropbear/initramfs/authorized_keys

echo 'DROPBEAR_OPTIONS="-I 300 -j -k -p 2222 -s -c cryptroot-unlock"' \
  >> /etc/dropbear/initramfs/dropbear.conf

echo 'IP=:::::eth0:dhcp' >> /etc/initramfs-tools/initramfs.conf
update-initramfs -u -k all

You then ssh -p 2222 root@your-ip during boot and the forced cryptroot-unlock command asks for the passphrase. Three things about it are worth knowing before you rely on it. The initramfs has its own host key, so your client will warn about a mismatch on port 2222 — that is expected, and the reason to give it a dedicated port. That host key and your authorized_keys sit on an unencrypted boot partition, readable by anyone holding the disk, so use an unlock key that does nothing else. And -s disables password logins in the initramfs, which is not optional.

The other detail that bites on small plans is the one from step three, and it bites hardest here. The initramfs runs before most of your RAM is available for anything comfortable, so a header formatted with a large Argon2id memory cost can fail to unlock on the very machine that created it. Format with --pbkdf-memory capped, and test the reboot while you still have nothing to lose.

Day two: what changes, and what does not

Very little, which is the point. An open LUKS volume is an ordinary block device; fsck, rsync, df and your backup tool all behave exactly as before. Kernel upgrades are unaffected because dm-crypt is in-tree. Growing the volume after a plan upgrade is two commands — cryptsetup resize then the filesystem's own resize — and needs no re-encryption.

Three habits are worth building. Rehearse the reboot on a schedule rather than discovering at 3 a.m. that a passphrase you never wrote down is the only copy. Keep the backups encrypted independentlyrestic or borg to an off-site target, which is a separate control from the volume and survives losing the box entirely; the daily off-site backup add-on runs $2.00/mo if you would rather not build it. And close the volume before you stop caring about the box: cryptsetup close secure before a planned shutdown, migration or reinstall means the key is out of memory before the disk stops being yours.

On policy, there is nothing to negotiate. You get full root on a KVM guest and what you do with the block layer is your business; encrypting your own volume is ordinary system administration, not an edge case. The acceptable use policy is about conduct — the hard floor is no CSAM and no terrorism — and has nothing to say about dm-crypt. What encryption does change is the shape of a hypothetical bad day: a powered-off volume that leaves this building is noise, and that is worth ten minutes of your time.

Frequently asked questions

Does full-disk encryption stop my hosting provider from reading my data?

Not while the server is running. Once the volume is unlocked the key is in the guest's RAM, and on any VPS that memory is on hardware the operator controls — a hypervisor can read it. What LUKS does completely is make the powered-off disk worthless: a drive returned to a vendor, a decommissioned node, an offline image. Anyone marketing disk encryption as protection from your own host is describing something that does not exist.

Can I encrypt a VPS that has no console or KVM-over-IP access?

An encrypted data volume, yes — entirely over SSH, with no boot risk, in about ten minutes. An encrypted root filesystem is different: every method needs the root offline, which on a headless machine means pivoting the running system into a RAM disk first. It works, and it is also how people lose servers. Convert at deploy time when the box has nothing on it, and use dropbear-initramfs so you can type the passphrase over SSH at boot.

How much performance does LUKS actually cost?

Low single-digit percent on any CPU with AES-NI, which means any modern x86-64 vCPU. Run cryptsetup benchmark and you will see aes-xts in the gigabytes per second — faster than the NVMe it sits on, so storage stays the bottleneck. On fast disks, --perf-no_read_workqueue and --perf-no_write_workqueue recover most of what is left at high queue depth.

What happens if I lose the passphrase?

The data is gone. There is no recovery mechanism, no master key held by anyone else and no support ticket that helps — that is the property you were buying. Mitigate it in advance: add a second passphrase in a separate keyslot with cryptsetup luksAddKey, and keep a header backup off the box. Note that a header backup taken before a passphrase rotation still opens the volume with the old passphrase, so destroy stale copies when you rotate.

Which VPS plan do I need to run an encrypted volume?

Encryption adds no RAM requirement and almost no CPU, so the tier is set by your workload rather than by LUKS. Cub (1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo) runs an encrypted volume without noticing; Scout (2 vCPU / 4 GB / 70 GB, $9.00/mo) is the comfortable size when the box also runs a database or a mail server. The one real constraint is disk, since the volume comes out of it.

Is encrypting my server allowed on your plans?

Yes — it is ordinary system administration. You get full root on a KVM guest with a real kernel, so dm-crypt, custom partitioning and anything else at the block layer are yours to configure. The acceptable use policy governs conduct, not configuration, and the hard floor there is no CSAM and no terrorism.

Do I need to encrypt swap as well?

Yes, and it is the step most guides skip. Swap is where kernel memory — including keys and decrypted buffers — ends up as a disk artefact, so a plaintext swap beside an encrypted volume leaks the thing you were protecting. Use a random key per boot via /etc/crypttab: nothing to manage and nothing to lose. Hibernation becomes impossible as a result, which on a VPS costs you nothing.

Deploy an offshore VPS in about a minute

No-KYC, crypto-paid, all-NVMe. Pick a tier, pay in Monero or any major coin, and get root in roughly 60 seconds.

Fenrir on guard