203 lines
8.9 KiB
Plaintext
203 lines
8.9 KiB
Plaintext
---
|
|||
|
|
title: Data-drive encryption (LUKS)
|
||
|
|
description: Optional LUKS2 encryption of the /docker data volume on new server installs. Encrypts customer data, databases, and container state at rest; adds a manual unlock step after every reboot.
|
||
|
|
sidebar:
|
||
|
|
order: 7
|
||
|
|
---
|
||
|
|
|
||
|
|
import { Aside } from '@astrojs/starlight/components';
|
||
|
|
import SuperAdmin from '~/content/partials/super-admin-callout.mdx';
|
||
|
|
import Support from '~/content/partials/support-link.mdx';
|
||
|
|
|
||
|
|
<SuperAdmin />
|
||
|
|
|
||
|
|
WHP can encrypt the **`/docker` data volume** — where customer site files,
|
||
|
|
databases, container state, and SSL material live — using LUKS2 (the same
|
||
|
|
disk-encryption layer used by every mainstream Linux distribution).
|
||
|
|
|
||
|
|
When enabled, anyone who walks off with the physical disk (or images it
|
||
|
|
offline) sees only ciphertext. The encryption key never lives on disk in
|
||
|
|
plaintext.
|
||
|
|
|
||
|
|
<Aside type="caution" title="Available only on new server installs">
|
||
|
|
Data-drive encryption must be enabled when the server is **first
|
||
|
|
provisioned**. There is no in-place "encrypt this existing server"
|
||
|
|
workflow today — switching a live server to encrypted storage requires a
|
||
|
|
manual data migration and is currently handled as a custom engagement.
|
||
|
|
Open a [support ticket](https://secure.anhonesthost.com/submitticket.php)
|
||
|
|
if you're considering this for an existing server.
|
||
|
|
</Aside>
|
||
|
|
|
||
|
|
## What changes if you enable it
|
||
|
|
|
||
|
|
The trade-off is one extra manual step every time the server reboots.
|
||
|
|
|
||
|
|
**At install time:**
|
||
|
|
- A strong passphrase (32 hex characters) is generated and **shown to you
|
||
|
|
once** in the install banner. You're responsible for saving it before
|
||
|
|
install completes — there is no recovery if it's lost.
|
||
|
|
|
||
|
|
**On every reboot (planned or unplanned):**
|
||
|
|
- The `/docker` volume comes up **locked**. The regular WHP control panel
|
||
|
|
at `:8443` is offline until you unlock it.
|
||
|
|
- The host itself boots normally — SSH, networking, monitoring, etc.
|
||
|
|
remain reachable.
|
||
|
|
- You unlock via either:
|
||
|
|
- **Web:** browse to `https://<server>:8444/`, sign in with the server's
|
||
|
|
`root` credentials, and paste the LUKS passphrase. The form redirects
|
||
|
|
you back to the regular panel after the volume mounts and services
|
||
|
|
come up (around 30 seconds end-to-end).
|
||
|
|
- **SSH:** run `/root/whp/scripts/whp-unlock-data-drive` and enter the
|
||
|
|
passphrase at the prompt. Same outcome.
|
||
|
|
|
||
|
|
**While unlocked:**
|
||
|
|
- The server runs identically to a non-encrypted server. No performance
|
||
|
|
penalty noticeable for typical hosting workloads.
|
||
|
|
|
||
|
|
<Aside type="caution" title="Plan for the reboot overhead">
|
||
|
|
Customer sites are unreachable from the moment the server reboots until
|
||
|
|
someone unlocks `/docker`. **Plan reboots accordingly** — and make sure
|
||
|
|
the right people have both the root credentials and the LUKS passphrase
|
||
|
|
before the first reboot.
|
||
|
|
</Aside>
|
||
|
|
|
||
|
|
## The security model in plain English
|
||
|
|
|
||
|
|
LUKS protects you against **data at rest** being read by someone without
|
||
|
|
the passphrase. Specifically:
|
||
|
|
|
||
|
|
- **Stolen or lost disk:** the device is unreadable without the passphrase.
|
||
|
|
- **Disk RMA / drive replacement:** you can return drives without secure
|
||
|
|
erase; the data on them is ciphertext.
|
||
|
|
- **Offline forensic imaging:** an attacker who can power off the server
|
||
|
|
and copy the disk gets ciphertext.
|
||
|
|
|
||
|
|
It does **not** protect against:
|
||
|
|
|
||
|
|
- **A live, running server being compromised** — once `/docker` is
|
||
|
|
unlocked, the data is plaintext in memory and accessible to anyone with
|
||
|
|
root on the host. (This is the same as any other Linux server.)
|
||
|
|
- **Lost passphrase** — there is no recovery key, no master override, no
|
||
|
|
vendor reset. Losing the passphrase means losing the data.
|
||
|
|
|
||
|
|
If your threat model is "compliance / customer expectations around
|
||
|
|
data-at-rest encryption," LUKS covers it. If it's "attacker has live
|
||
|
|
shell on the server," LUKS does nothing additional — you need separate
|
||
|
|
controls (access policy, monitoring, segmentation).
|
||
|
|
|
||
|
|
## The unlock surface in detail
|
||
|
|
|
||
|
|
The unlock daemon (`whp-locked-unlock.service`) is a small standalone
|
||
|
|
HTTPS server that runs **independently** of the main control panel
|
||
|
|
(Apache + PHP-FPM). It exists for exactly one purpose: prompt for and
|
||
|
|
validate the LUKS passphrase, then hand off to the helper that opens the
|
||
|
|
volume and starts the customer-facing services.
|
||
|
|
|
||
|
|
- **Port:** `8444` (separate from the regular panel on `:8443` / `:8080`)
|
||
|
|
- **TLS:** if your server has a real Let's Encrypt certificate for its
|
||
|
|
hostname (the usual case on AnHonestHost-managed installs), the daemon
|
||
|
|
uses that. If not, it uses the same self-signed cert that the regular
|
||
|
|
panel falls back to.
|
||
|
|
- **Authentication:** the server's root credentials via PAM (same login
|
||
|
|
as the regular control panel), **plus** the LUKS passphrase. Both must
|
||
|
|
be correct.
|
||
|
|
- **Rate limit:** five failed attempts per IP per five minutes triggers a
|
||
|
|
short lockout. You can unlock from another IP, from SSH, or wait for
|
||
|
|
the window to expire.
|
||
|
|
- **Auto-stop:** once the unlock succeeds, the daemon exits cleanly. It
|
||
|
|
comes back automatically on the next reboot.
|
||
|
|
|
||
|
|
After the web unlock, the regular control panel at `:8443` becomes
|
||
|
|
reachable within ~30 seconds (the time it takes Docker, Apache, and the
|
||
|
|
boot orchestrator to start the customer containers).
|
||
|
|
|
||
|
|
## Header backup — critical for recovery
|
||
|
|
|
||
|
|
The LUKS2 header is a small region (~16 MB) at the start of the
|
||
|
|
encrypted device that holds the keyslot data. If that region gets
|
||
|
|
corrupted (bad sectors, partition table accident, careless `dd`), the
|
||
|
|
data is unrecoverable **even with the correct passphrase**.
|
||
|
|
|
||
|
|
WHP keeps a header backup automatically:
|
||
|
|
|
||
|
|
- **Initial backup** at `/etc/whp/luks-header.backup`, created during the
|
||
|
|
install.
|
||
|
|
- **Daily refresh** via cron — only writes a new file when the header
|
||
|
|
has actually changed (i.e. on passphrase rotation).
|
||
|
|
- **Rolling 30-day history** at `/var/lib/whp/luks-headers/`.
|
||
|
|
- **Off-host upload** if you've configured an rclone remote named
|
||
|
|
`whp-system-backup`. We strongly recommend setting this up so the
|
||
|
|
header isn't only on the same disk it's protecting.
|
||
|
|
|
||
|
|
In a header-corruption scenario, restoring is a one-command operation
|
||
|
|
using the saved backup, then unlocking with your passphrase as normal.
|
||
|
|
|
||
|
|
## Rotating the passphrase
|
||
|
|
|
||
|
|
If you need to change the LUKS passphrase (staff rotation, suspected
|
||
|
|
compromise of the saved copy, etc.), do it in this order:
|
||
|
|
|
||
|
|
1. **Add the new passphrase** as a second keyslot — the volume now
|
||
|
|
accepts either one.
|
||
|
|
2. **Verify the new passphrase works** with a non-destructive test.
|
||
|
|
3. **Remove the old passphrase** from its keyslot.
|
||
|
|
|
||
|
|
The full command sequence is documented in the operator runbook on the
|
||
|
|
server itself (`/root/whp/docs/LUKS_RUNBOOK.md`). After any keyslot
|
||
|
|
change, the daily header backup picks up the new header SHA and uploads
|
||
|
|
a fresh copy on its next run.
|
||
|
|
|
||
|
|
## Things to know before you commit to it
|
||
|
|
|
||
|
|
- **Lost passphrase = lost data.** This is the single most important
|
||
|
|
thing to plan around. Treat the passphrase the way you'd treat a
|
||
|
|
payment-processor master key.
|
||
|
|
- **Every reboot needs someone awake.** Auto-restart watchdogs, kernel
|
||
|
|
updates that trigger a reboot, and power events all become events
|
||
|
|
that require manual intervention. If your team can't respond within
|
||
|
|
your acceptable downtime window, this isn't the right fit.
|
||
|
|
- **Server-side backups still matter.** Encryption protects against
|
||
|
|
data theft. It does not protect against data loss. Your customer
|
||
|
|
backup configuration and the LUKS header backup are independent
|
||
|
|
concerns — both need to be in place.
|
||
|
|
- **Boot drive is unencrypted.** The OS, the control panel itself, and
|
||
|
|
the LUKS configuration file all live on the unencrypted boot drive.
|
||
|
|
This is intentional — it lets the unlock UI come up and lets you SSH
|
||
|
|
in for recovery before `/docker` is available.
|
||
|
|
|
||
|
|
## When LUKS is **not** the right choice
|
||
|
|
|
||
|
|
- Servers where unattended reboots are operationally required (e.g.
|
||
|
|
automated kernel updates with reboot on a recurring schedule with no
|
||
|
|
human in the loop).
|
||
|
|
- Servers where the only "threat" is the existing AnHonestHost
|
||
|
|
operational controls — if your compliance posture doesn't ask for
|
||
|
|
data-at-rest encryption specifically, the operational overhead may
|
||
|
|
not be worth it.
|
||
|
|
- Existing servers with live customer data on them — wait for the
|
||
|
|
retrofit workflow rather than attempting a manual migration without
|
||
|
|
guidance.
|
||
|
|
|
||
|
|
## Setting this up on a new server
|
||
|
|
|
||
|
|
If you're spinning up a fresh server and want data-drive encryption,
|
||
|
|
mention it in the provisioning ticket and we'll configure it as part of
|
||
|
|
the install. We'll send you the generated passphrase through a secure
|
||
|
|
channel and confirm you have it stored before the server is handed over.
|
||
|
|
|
||
|
|
For technically-inclined customers running WHP themselves, the install
|
||
|
|
flag is documented in the operator runbook that ships on every server at
|
||
|
|
`/root/whp/docs/LUKS_RUNBOOK.md`.
|
||
|
|
|
||
|
|
## Related
|
||
|
|
|
||
|
|
- [Server settings & services](/whp/admin/server-settings/) — restart
|
||
|
|
individual services after an unlock, view system info.
|
||
|
|
- [Backups](/whp/admin/backups/) — independent of LUKS; both should be
|
||
|
|
configured.
|
||
|
|
- [Admin overview](/whp/admin/overview/) — other super-admin features.
|
||
|
|
|
||
|
|
## Still stuck?
|
||
|
|
|
||
|
|
<Support />
|