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_SECRETENCRYPTION_KEYSCREEN_PROXY_SECRETSANDBOX_SUPERVISOR_TOKENRAKAZO_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_SECRETcasually 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
.envand volumes together; treat.envas secret material in transit.
Related
Optional credential storage
Stored credentials can use self-hosted Infisical while short-lived secrets stay encrypted in Postgres. See Infisical setup, migration, and rollback.