Encryption at rest
Crewship stores per-agent memory on the host filesystem — under the storage base path (CREWSHIP_STORAGE_BASE_PATH, default
/var/lib/crewship) at crews/{crewID}/agents/{slug}/.memory/
— as plaintext markdown plus a SQLite database next to it. That’s
the right default for ergonomics (operators can grep, back up,
edit), but it leaves the operator on the hook for at-rest
encryption when the deployment carries PII.
PR-E F6 (PERSONA.md + per-user peer cards) deliberately keeps the
encryption layer out of the application — application-layer
encryption of small markdown files would bloat the codebase, add a
key-management problem, and break the “operators can grep their
own data” affordance. Instead we recommend filesystem-layer
encryption configured at deployment time. Two production-proven
options are documented below.
Threat model
The encryption-at-rest layer protects against ONE thing: a host disk leaving the data centre (stolen drive, decommissioned VM, unmounted backup tape) with the data unrecoverable to whoever finds it. For those threats, layered controls (auth, RBAC, container isolation, audit logging) carry the load. Encryption-at-rest is the “if the disk walks off” insurance.When you should turn this on
- Always for production deployments handling EU customer data (GDPR Article 32 baseline). The default for new EU-region installs is encryption-on, configured at provisioning time.
- Strongly recommended for any deployment carrying customer
PII in agent memory (
AGENT.mdcontent, peer cards naming specific operators). - Optional for single-operator local development setups where the laptop disk is already FileVault / BitLocker / LUKS encrypted at the OS layer.
Option A — LUKS (block-level, recommended for new hosts)
LUKS is the canonical Linux block-encryption layer.By default both
CREWSHIP_DATA_DIR (database, config) and
CREWSHIP_STORAGE_BASE_PATH (the per-agent .memory/ trees described
above) resolve to /var/lib/crewship, so one LUKS volume covers both.
If you’ve pointed CREWSHIP_STORAGE_BASE_PATH at a separate disk,
LUKS-encrypt that disk too — the agent memory is the most sensitive
at-rest surface.One-time setup
Boot-time unlock
For unattended boot, add an entry to/etc/crypttab:
Option B — eCryptfs (per-directory, for existing hosts)
eCryptfs encrypts at the filesystem layer above an existing mount, useful when you can’t (or don’t want to) reformat the underlying volume. Slower than LUKS for large workloads but trivial to layer onto an existing crewship install.Boot-time mount
Add an/etc/fstab entry referencing the eCryptfs auto-mount
helper, or use pam_ecryptfs to mount on first login.
Verifying
After setup, do two sanity checks before declaring success. The commands differ between Option A (LUKS, block-device) and Option B (eCryptfs, filesystem overlay) because there’s no/dev/mapper/...
device under eCryptfs — the encryption happens in the filesystem
layer over a regular directory.
Verify LUKS (Option A)
Verify eCryptfs (Option B)
Backups
Backups taken viacrewship backup create read the volume while
it’s unlocked. The backup tool encrypts the bundle natively
(passphrase or age --recipient); use --no-encrypt only if you
intend to layer your own protection. If you need to wrap a
plaintext bundle yourself, run it through GPG / age before storing
it off-host:
Application-layer encryption (deliberately out of scope)
PRs that add per-row encryption inside
crewshipd for these
small markdown files have come up and been rejected. The
trade-off ratio doesn’t work:- Cost: a key-management surface, a per-row encrypt/decrypt path,
a migration story for existing plaintext, broken
grep/crewship memory searchergonomics. - Benefit: marginal over filesystem encryption for the dominant threat (lost disk), zero benefit for the other threats already enumerated above.