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 rakazo / rakazo). 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
  • RAKAZO_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.

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 (RAKAZO_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

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.