# Enterprise deployment guide This guide complements [`../SECURITY.md`](../SECURITY.md) with the operational steps a regulated or security-conscious organization needs to deploy Arboretum with confidence. ## 1. Remote access: Tailscale Serve (recommended) Never open a public port. Keep the default `127.0.0.1` bind and put Arboretum behind Tailscale Serve: ```bash # on the host running arboretum (default bind 127.0.0.1:7317) tailscale serve --bg 7317 ``` This gives you TLS, a stable `*.ts.net` hostname, and tailnet identity. Then add that origin to the allow-list so the strict Origin check accepts it: ```bash arboretum --allow-origin https://my-host.tailnet.ts.net ``` The `--i-know-this-exposes-a-terminal` flag exists only as an escape hatch for non-loopback binds; it is **never** a deployment mode and is never injected automatically by `arboretum install`. ## 2. Encryption at rest Sensitive secrets (the HMAC server secret and the VAPID private key) are encrypted with AES-256-GCM before being stored in SQLite. Token values are never stored — only their SHA-256 hashes. For **strong** protection (key not co-located with the database), provide a passphrase via the environment instead of the on-disk key file: ```bash ARBORETUM_SECRET_KEY='' arboretum ``` - Store this passphrase in your secrets manager / KMS, **separately** from database backups. - Without it, the key is auto-generated in `dataDir/secret.key` (`0o600`). This still protects a leaked database copy, but not a full `dataDir` compromise. - Rotating the passphrase requires re-encrypting existing values; the simplest path is to revoke and recreate the bootstrap token after rotation. ## 3. Filesystem permissions On startup Arboretum forces `dataDir` to `0o700` and the database files (`*.db`, `-wal`, `-shm`) to `0o600`. Verify after first run: ```bash stat -c '%a %n' ~/.local/share/arboretum ~/.local/share/arboretum/*.db # expect: 700 …/arboretum and 600 …/arboretum.db ``` Keep `$HOME` private (standard `0o700`). If you relocate data with `--db` or `XDG_DATA_HOME`, make sure the target directory is not world-readable. ## 4. Audit logging All sensitive mutations are recorded in an append-only `audit_logs` table: token create/revoke, login success/failure, settings changes, secret generation, push subscribe/unsubscribe, group CRUD, and data erasure. Query it via the API (paginated): ```bash curl -s -H "Authorization: Bearer $TOKEN" \ 'http://127.0.0.1:7317/api/v1/audit-logs?limit=100' ``` The audit log never contains secret values — only non-sensitive metadata (ids, labels, counters). It is also visible in the dashboard under **Settings → Security & compliance**. ## 5. GDPR (data subject requests) - **Export**: `GET /api/v1/data/export` returns every record tied to the authenticated token (token metadata, push subscriptions, session history, settings) as JSON. Also available as a one-click download in **Settings → Security & compliance**. - **Erasure**: `POST /api/v1/data/delete-my-data` is a two-step call — the first response returns a `confirm` code that must be POSTed back to execute. It purges the token's push subscriptions and revokes the token (unless it is the last active one). ## 6. Backups & retention - Back up the SQLite database (`arboretum.db`) with the WAL checkpointed. Treat backups as sensitive. - If you use `ARBORETUM_SECRET_KEY`, back the key up **separately** — a database backup is useless (and safe) without it, which is the point. - Session history is retained until the database is reset. To start clean, stop the service and remove the database file. ## 7. Logging hygiene The log level is controlled by `ARBORETUM_LOG` (default `info`). Do **not** run `debug`/`trace` in production: verbose levels may log request metadata. Keep `info` or higher. ## 8. Supply chain Each published release ships with a CycloneDX SBOM (`sbom.json`) generated in CI, so you can scan the dependency tree for known vulnerabilities before deploying.