What runs

Every container on the box, what each one does, and which of them may talk to anything outside.

On this page

Outside the house

  • Your laptop or phonethrough Tailscale, at your domain, or on your own network
  • Your mailboxIMAP, read only
  • The model you chosetext of each document
  • Your backup targetencrypted snapshots, nightly

The box

  • tailscaleoptional: serves the app on your tailnettalks to your laptop or phone
  • caddyoptional: serves the app at your domain, over HTTPStalks to your laptop or phone
  • webthe appinternal only
  • apiHTTP API, sessions, migrationsinternal only
  • workerOCR and text extraction; the only process that opens a documentno route out
  • suggestertitles, categories, dates, summariestalks to the model you chose
  • mailfetchreads connected mailboxestalks to your mailbox
  • backupnightly dump and snapshot, monthly restore testtalks to your backup target
  • postgres · redisstate and queuesinternal only

/data one encrypted volume: documents, database, queues, secrets

Nothing on the box listens on the public internet unless you serve it at a domain, and then only Caddy does. Each container that talks outside talks to one thing.

The containers#

ContainerDoesNetwork
tailscaleOptional. Serves the app on your tailnet over HTTPSWhen present, the only thing reachable, and only from your tailnet
caddyOptional. Serves the app at your domain over HTTPS, with a certificate from Let's Encrypt, and lets the first account be created only through the setup linkWhen present, the only thing listening, on ports 80 and 443
webThe appNo host port of its own behind Tailscale or Caddy; otherwise a port on the address you chose
apiHTTP API, migrations, sessionsInternal, plus mail autodiscover during setup
workerOCR, thumbnails, and text extractionNo route out
suggesterTitles, categories and dates from the text, via the model you chose or noneOut to that provider only
mailfetchReads connected mailboxes over IMAP; the only process that unseals mail passwordsOut to IMAP hosts only
backupNightly database dump and snapshot, monthly restore testOut to the backup target only
postgres, redisState and queues, on the encrypted volumeInternal

Isolation#

The OCR toolchain has a long history of vulnerabilities, and email-in lets strangers hand you a file. The worker is isolated in a container with access to internal services, no direct internet route, a read-only filesystem, no root privileges, and a timeout per job. Isolation limits exposure; it does not make malicious files harmless.

Keys#

Volume passphrase, typed at boot ————— protects the powered-off box
  └─ master key, a file on that volume —— protects document keys and sealed secrets
       └─ a key per file ————————————— protects each document independently

Every document is encrypted under a key of its own, wrapped by the master key. The master key lives only on the encrypted volume and on the envelope. Rotating it re-wraps the per-file keys rather than re-encrypting each document.

The database keeps each document's text in the clear so that search is fast, which is why the data volume must be encrypted and the installer refuses otherwise.

Protections and limits#

SomeoneGetsProtection and remaining limits
A burglar who takes the boxA powered-off applianceWith manual unlocking, the encrypted volume requires a passphrase kept separately
A breach at the backup providerSnapshotsSnapshots are encrypted before upload; keep recovery keys separate from the provider
An attacker on the internetNothing to connect to, unless you chose the internetZero inbound ports on the tailnet path and on your own network. On the internet path, Caddy and the sign-in page, which needs a password and an authenticator code; the first account can only be created through the setup link
A malicious PDF sent by emailCode running in the OCR workerThe worker has no direct internet access or root privileges, but can reach required internal services
Someone with a stolen family laptopA sessionAn existing session may still allow access. Revoke it promptly; MFA protects new sign-ins, not an already authenticated session

Not defended against, by design: a compromised running server, which holds plaintext; a malicious owner account; and the model provider, which sees document text. There is no end-to-end encryption between household members. The repository's security page states this in full.