Docs menu

Self-hosting

Self-host secrets checklist

Required and optional credentials for published-images and Compose deploys.

Never commit .env, never paste secret values into issues/PRs, and never overwrite an existing .env without an explicit backup and operator consent.

Published images: what the installer fills

bash install-images.sh (without a pre-existing .env) copies .env.images.example and fills empty required keys with openssl:

Key Installer fill Role
POSTGRES_PASSWORD openssl rand -hex 16 Postgres owner password inside Compose (migrations)
POSTGRES_APP_PASSWORD openssl rand -hex 16 Password of the app’s rakazo_app login, which row-level security applies to
BETTER_AUTH_SECRET openssl rand -hex 32 Auth/session signing
ENCRYPTION_KEY openssl rand -hex 32 Encrypts stored credentials at rest
SCREEN_PROXY_SECRET openssl rand -hex 32 Signs short-lived /novnc/* screen capabilities
SANDBOX_SUPERVISOR_TOKEN openssl rand -hex 32 API ↔ sandbox supervisor auth

Re-runs preserve an existing .env (they do not rotate secrets); they only append POSTGRES_APP_PASSWORD when an older .env lacks it. Empty required keys still fail closed at Compose validate time (${VAR:?Set … in .env}).

Manual generation (same shapes the installer uses):

openssl rand -hex 16   # POSTGRES_PASSWORD, POSTGRES_APP_PASSWORD
openssl rand -hex 32   # BETTER_AUTH_SECRET, ENCRYPTION_KEY, SCREEN_PROXY_SECRET, SANDBOX_SUPERVISOR_TOKEN

Source-checkout .env.example also requires POSTGRES_PASSWORD and POSTGRES_APP_PASSWORD (same openssl rand -hex 16 shape) for infra/compose/docker-compose.yml. Put them in host-side DATABASE_MIGRATION_URL and DATABASE_URL when using the optional docker-compose.postgres-host.yml overlay. Keep the password URI-safe: Compose interpolates it into DATABASE_URL the same way the images stack does. Hex from openssl rand is safe; characters such as @ : / ? # % are not.

Existing source-checkout pgdata volumes keep the user, password, and database from first init (often the former hardcoded orkbot / orkbot). Keep those values in .env, or change them in place with ALTER ROLE / rename. Recreate the volume only after a backup (or when the data is disposable); docker compose down -v deletes all Postgres state.

Source-checkout .env.example asks for a 64-hex ENCRYPTION_KEY in comments; published-images installer uses 32 bytes of hex (64 hex chars) via openssl rand -hex 32. Prefer long independent random values either way. Do not reuse one string across keys.

Distinctness rules

These must be independent random values (do not copy-paste the same secret into multiple keys):

  • BETTER_AUTH_SECRET
  • ENCRYPTION_KEY
  • SCREEN_PROXY_SECRET
  • SANDBOX_SUPERVISOR_TOKEN
  • ORKBOT_UPDATER_TOKEN (only if the updater profile is enabled; ≥32 chars, also distinct from the four above)

Rotating ENCRYPTION_KEY after credentials were stored makes old ciphertext unreadable. Keep the original key for an existing deployment unless you intentionally wipe encrypted material.

ENCRYPTION_KEY also derives the default master key for chat, memory and file encryption, so changing it also makes that content unreadable. To move content off it, set ENCRYPTION_MASTER_KEYS and run the rotation in content-encryption.md, which re-wraps the space keys without stranding content. Keep ENCRYPTION_KEY unchanged afterwards: stored credentials still depend on it.

With MASTER_KEY_PROVIDER=aws-kms, these and the other API and worker secrets can be kept in .env wrapped by the key manager instead of in plaintext (wrapped settings).

Optional keys (leave blank if unused)

From .env.images.example (images installer). Leave blank if unused:

Key(s) When needed
OPENROUTER_API_KEY Deployment-wide OpenRouter models
TYPESAFE_API_KEY Optional TypeSafe Jev Auto Review verifier (ORKBOT_AUTO_REVIEW_PROVIDER=jev)
COMPOSIO_API_KEY Composio managed catalog
E2B_API_KEY / DAYTONA_API_KEY / BOAT_API_KEY Remote computers when SANDBOX_PROVIDER is not docker
EMAIL_PROVIDER / EMAIL_API_KEY / SMTP_URL / EMAIL_FROM Optional account email via Resend API or SMTP
EXPO_ACCESS_TOKEN Mobile push when the Expo project enables enhanced push security
Messaging tokens (Slack, Telegram, …) Only if you enable those surfaces

Optional APNS_VOIP_KEY_ID, APNS_VOIP_TEAM_ID, and APNS_VOIP_PRIVATE_KEY enable iOS VoIP ringing. Keep the .p8 contents in the secret manager.

Blank optional keys are normal for a minimal published-images boot. Pipedream Connect keys appear only in source/Compose .env.example, not the images example.

Operator workflow

bash install-images.sh --prepare-only   # creates .env + fills empties
# inspect key NAMES only if debugging; never log values
bash install-images.sh                  # pull + up; preserves .env
curl -fsS http://127.0.0.1:3100/internal/health

If sandbox in /internal/health is "none" or the supervisor never becomes healthy, check that SANDBOX_SUPERVISOR_TOKEN is set and non-empty for the Docker computer path. A missing token is a setup failure, not an “optional tighten later” item.

Recovery without reprinting secrets

  • Lost UI password: use SMTP recovery if configured; otherwise operator identity recovery is out of band (DB). Prefer not to rotate BETTER_AUTH_SECRET casually on a live deploy.
  • Lost .env: from backup only. Recreating random secrets on a volume that still holds Postgres data will desynchronize passwords and encryption.
  • Moving hosts: copy .env and volumes together; treat .env as secret material in transit.

Optional credential storage

Stored credentials can use self-hosted Infisical while short-lived secrets stay encrypted in Postgres. See Infisical setup, migration, and rollback.