Skip to main content

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.
Encryption-at-rest does NOT protect against:
  • A live Crewship process being compromised (the encryption keys are in RAM by definition).
  • An operator with shell access to the host (the mount is transparent once unlocked).
  • An attacker who can mount the volume via crewshipd itself (the bind mount sees plaintext).
  • A backup tool that copies the unmounted/unlocked filesystem (it sees plaintext too).
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.md content, 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.
LUKS is the canonical Linux block-encryption layer.
Configure LUKS on the disk hosting $CREWSHIP_DATA_DIR BEFORE the first crewship process starts; migrating an existing plaintext volume in place is possible but slow and risky.
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:
The keyfile lives outside the LUKS volume (typically a separate ramdisk, a TPM-sealed file, or a remote secrets fetch). NEVER store the keyfile on the same disk you’re trying to encrypt — defeats the purpose.

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 via crewship 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:
Or, more sustainably, point the backup tool at a separate encrypted mount.

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 search ergonomics.
  • Benefit: marginal over filesystem encryption for the dominant threat (lost disk), zero benefit for the other threats already enumerated above.
If your compliance posture genuinely requires application-layer encryption (e.g. you legitimately can’t trust the host operator), the right escape hatch is a sidecar HSM-backed envelope encryption service that the application calls per-file — but that’s a Phase 2 roadmap item, not the F6 baseline.