NODE_ENV=development # Compose Postgres role (source-checkout and images stacks). Generate with: # openssl rand -hex 16 # Use a URI-safe value (hex from openssl is fine). Special characters such as # @ : / ? # % break DATABASE_URL interpolation inside Compose. # Put the same value in DATABASE_URL when using the optional host publish overlay. # Existing pgdata volumes keep user/password/db from first init; keep those # values in .env, or ALTER ROLE / rename in place. Recreate the volume only # after a backup (or when disposable); down -v deletes all Postgres state. POSTGRES_USER=rakazo POSTGRES_PASSWORD= POSTGRES_DB=rakazo # The app's own login (rakazo_app): no superuser, no schema changes, and subject # to row-level security. `pnpm db:migrate` creates it with this password. # Generate with: openssl rand -hex 16 POSTGRES_APP_PASSWORD= # Optional host-publish overlay port. Keep the DATABASE_*_URL ports in sync. POSTGRES_HOST_PORT=5433 # Host-side clients only (pnpm db:migrate / pnpm dev). Requires the postgres-host # overlay so 127.0.0.1:5433 is published. Inside Compose, api/worker ignore these # and connect to the postgres service with POSTGRES_* above. # The app connects as the runtime login; migrations run as the owner. DATABASE_URL=postgres://rakazo_app:REPLACE_WITH_POSTGRES_APP_PASSWORD@127.0.0.1:5433/rakazo DATABASE_MIGRATION_URL=postgres://rakazo:REPLACE_WITH_POSTGRES_PASSWORD@127.0.0.1:5433/rakazo BETTER_AUTH_SECRET=replace-with-32-plus-character-secret # Local loopback: localhost and 127.0.0.1 are interchangeable browser hosts. BETTER_AUTH_URL=http://127.0.0.1:5173 API_URL=http://127.0.0.1:3100 # Listener address. Keep loopback unless a container or trusted reverse proxy must reach the API. API_HOST=127.0.0.1 # Reverse proxies whose forwarded client address the API believes: IPs, CIDR ranges, or hostnames. # Empty trusts loopback; in a container, also the networks it is attached to (local-networks). # none trusts no proxy. TRUSTED_PROXIES= # The header those proxies set. Default x-forwarded-for. CLIENT_IP_HEADER= WEB_ORIGIN=http://127.0.0.1:5173 # Optional https:// origins added to the web Content-Security-Policy, space-separated, for a # script your CDN injects (for example analytics). See docs/self-host.md#content-security-policy. # RAKAZO_CSP_SCRIPT_SRC=https://static.example.com # RAKAZO_CSP_CONNECT_SRC=https://beacon.example.com # Optional: refuse clients built before these UTC times (YYYYMMDDHHMMSS) so they update. # See docs/self-host.md#client-updates. # RAKAZO_MIN_CLIENT_BUILD=web=20261022093015,mobile=20261001000000 PUBLIC_POSTHOG_KEY= PUBLIC_POSTHOG_HOST=https://us.i.posthog.com SIGNUPS_ENABLED=true # Opt-in: reject new passwords found in Have I Been Pwned (sends a 5-character hash prefix). AUTH_BREACHED_PASSWORD_CHECK_ENABLED=false # Empty keeps the stored allowlist. A non-empty list is applied on every API start. SIGNUP_ALLOWLIST= # Optional: native apps allowed to use this domain's passkeys. See docs/self-host.md#passkeys. PASSKEY_APPLE_APP_IDS= PASSKEY_ANDROID_CERT_SHA256= ENCRYPTION_KEY=replace-with-64-random-hex-characters # Optional content master keys, active first: id:key,older-id:key. See docs/content-encryption.md. ENCRYPTION_MASTER_KEYS= # on|off: encrypt new content at rest. Empty is off in development and on elsewhere. CONTENT_ENCRYPTION= # Optional credential storage; API and worker must share this scope. See docs/infisical-secrets.md. SECRET_STORE=encrypted INFISICAL_URL= INFISICAL_ALLOW_INSECURE_HTTP=false INFISICAL_CLIENT_ID= INFISICAL_CLIENT_SECRET= INFISICAL_PROJECT_ID= INFISICAL_ENVIRONMENT= INFISICAL_FOLDER= DATA_DIR=./data # Optional: keep computer homes and artifacts in S3-compatible storage instead of DATA_DIR. # Set the bucket to turn it on. See docs/self-host.md#shared-storage-migration. OBJECT_STORAGE_BUCKET= OBJECT_STORAGE_ENDPOINT= OBJECT_STORAGE_REGION= OBJECT_STORAGE_ACCESS_KEY_ID= OBJECT_STORAGE_SECRET_ACCESS_KEY= OBJECT_STORAGE_PREFIX= OBJECT_STORAGE_PATH_STYLE= SANDBOX_SUPERVISOR_URL=http://127.0.0.1:7091 # Dedicated credentials (distinct from BETTER_AUTH_SECRET). Required for Docker sandboxes / # screen proxy outside local development. SANDBOX_SUPERVISOR_TOKEN=replace-with-32-plus-character-supervisor-token # Per-bot-computer ceilings. Defaults 2g / 2 CPUs / 2048 pids; "0", "none" or "unlimited" removes # one. Memory also caps swap, and must be at least 6m (Docker's own minimum). RAKAZO_COMPUTER_MEMORY= RAKAZO_COMPUTER_CPUS= RAKAZO_COMPUTER_PIDS_LIMIT= SCREEN_PROXY_SECRET=replace-with-32-plus-character-screen-proxy-secret SANDBOX_PROVIDER=docker # none | emulator | cursor. Live agents require a key and an explicitly authorized Space. CLOUD_AGENT_PROVIDER=none CURSOR_API_KEY= # Grant this Space access to the repositories connected to the Cursor credential. CLOUD_AGENT_SPACE_ID= # Optional Docker daemon socket. Defaults to /var/run/docker.sock (Unix) or # //./pipe/docker_engine (Windows). Set for rootless Docker, Colima, or custom paths. # DOCKER_HOST takes precedence over DOCKER_SOCKET when both are set. # DOCKER_SOCKET= # Enable for a host-run supervisor using a local Docker Desktop daemon: control # uses a random token-guarded 127.0.0.1 port because container IPs are unreachable. # Leave unset for Compose, remote Docker daemons, or native Linux Docker Engine. # Changing this setting replaces incompatible computers on their next provision; # their mounted homes are preserved. # SANDBOX_CONTROL_VIA_LOOPBACK=true DAYTONA_API_KEY= DAYTONA_API_URL= DAYTONA_TARGET= # Optional snapshot name for bot computers; unset uses the Daytona server default. DAYTONA_SNAPSHOT= CREATEOS_SANDBOX_API_KEY= # Optional CreateOS API base URL; defaults to https://api.sb.createos.sh. CREATEOS_SANDBOX_BASE_URL= # Optional CreateOS sandbox shape/rootfs; defaults to s-2vcpu-2gb and desktop:1. CREATEOS_SANDBOX_SHAPE= CREATEOS_SANDBOX_ROOTFS=desktop:1 # Railway workspace/account API token; keep it on the API and worker only. RAILWAY_MAX_WORKSPACE_FILE_BYTES=67108864 RAILWAY_API_TOKEN= # Railway supplies this automatically when hosted there. RAILWAY_ENVIRONMENT_ID= BOAT_API_KEY= # Optional Boat API base URL; defaults to https://boat.dev/api/v1. BOAT_API_URL= AGENT_RUNTIME=pi # Optional Pi traces via OTLP/HTTP; empty endpoint means no SDK initialization. OTEL_EXPORTER_OTLP_ENDPOINT= # Standard comma-separated key=value headers; keep credentials private. OTEL_EXPORTER_OTLP_HEADERS= OTEL_SERVICE_NAME=rakazo-worker # Prompt, response and tool content stays excluded unless exactly true. OTEL_CAPTURE_CONTENT=false # Opt-in Pi JSONL session recording under DATA_DIR/pi-sessions. Default off: # transcripts are unencrypted on disk and unsuitable for multi-tenant hosted DATA_DIR. # PI_SESSION_RECORDING=true # Optional ticket board; enable on both API and worker. TICKET_BOARD_ENABLED=false # Optional bot calls and hold-to-talk; enable on both API and worker. PHONE_CALLS_ENABLED=false # Minimum minutes between bot calls to the same user (default 2). PHONE_CALL_COOLDOWN_MINUTES=2 # Seconds before an unanswered call expires (default 45). PHONE_CALL_RING_SECONDS=45 # Per-file chat/computer upload limit in MiB (positive integer; default 10). MAX_UPLOAD_SIZE_MB=10 # Off by default. Replies longer than this are read aloud as a summary from the bot's model. # VOICE_SUMMARY_MIN_CHARS=600 WAKEUP_DRIVER=graphile # Keep app-owned PostgreSQL pools bounded. Leave DB_POOL_MAX unset so each # process keeps its default (api 4, worker 8). A set value applies to both — # size it for the worker (three LISTEN clients + leadership + query headroom; # Graphile requires at least 6). Agent runs share this pool between operations. # DB_POOL_MAX=8 # Concurrent legacy interactive queue deliveries during rolling upgrades. # New agent runs dispatch directly from Postgres and do not occupy Graphile slots. # Background queue dispatch and maintenance each have one additional worker. GRAPHILE_WORKER_CONCURRENCY=4 # Model stream retries: integer 0-5; default 1. Invalid or blank values use 1. # More retries allow longer turns during transient provider failures. MODEL_STREAM_MAX_RETRIES=1 # Characters a message_user progress update may carry before it is cut off: positive # integer; default 500. Mid-turn narration keeps the 500 cap. # RAKAZO_MESSAGE_USER_MAX_CHARS=500 # Bot-to-bot messages one chain may carry before the next is refused: positive integer; # default 6. A person's own message starts a fresh chain. # BOT_MESSAGE_MAX_HOPS=6 # Pause or stop computers after this many idle ms. Minimum 30000; 0 disables idle sleep. # Set 0 when self-hosting with Docker, where an idle computer costs nothing, to keep long-running apps and sessions up. # E2B, CreateOS and Boat still apply their own timeouts. SANDBOX_IDLE_MS=600000 # Maximum uptime on providers that bill while running. Minimum 60000; 0 disables the cap. COMPUTER_MAX_ACTIVE_MS=7200000 # Comma-separated model ids on centrally managed local / openai-compatible endpoints that accept images. # User-connected OpenAI-compatible models use the per-connection Supports images setting instead. # Declared ids get input ["text","image"] so screenshot computer tools stay available. RAKAZO_LOCAL_VISION_MODELS= RAKAZO_OPENAI_COMPATIBLE_VISION_MODELS= SANDBOX_COMMAND_TIMEOUT_MS=300000 # Optional limit on active bot desktops per Docker Team Computer. # 0 leaves capacity to the machine; desktops and Chrome start only when needed. SANDBOX_TEAM_SCREEN_LIMIT=0 # Optional cap on Computer records still backing live bots, per user. Each record # becomes a sandbox container once provisioned, so the cap bounds the containers # one user can create. 0 means no configured cap (default). SANDBOX_MAX_COMPUTERS_PER_USER=0 # Optional limit on total concurrent bot computer containers per space in Docker sandboxes. # 0 (or unset) means unlimited. Set a positive integer to cap containers per space. SANDBOX_MAX_COMPUTERS_PER_SPACE=0 # Docker sandboxes only. "restricted" keeps computer egress to the public internet only # (blocks the host, LAN/RFC1918, and cloud metadata endpoints) and needs # infra/compose/restrict-computer-egress.sh run once on the Docker host; computers refuse # to start until it has. Compose defaults to restricted. A host-run supervisor (pnpm dev, # usually Docker Desktop, which cannot take the rules) defaults to open. See docs/self-host.md. # SANDBOX_COMPUTER_EGRESS=open # Docker sandboxes only. Comma-separated DNS server IPs for bot computers, instead of the # host's resolvers. Set it with restricted egress when the host's resolver has a private # address (a cloud VPC or LAN resolver), which the ruleset blocks. See docs/self-host.md. # SANDBOX_COMPUTER_DNS=1.1.1.1,1.0.0.1 # Optional per-turn tool-call fuse for the Pi agent runtime. Unset, empty, or 0 # means unlimited (default). Set a positive integer to soft-stop a turn that # exceeds the budget and still emit a final assistant message. MAX_TOOL_CALLS_PER_TURN= # Deployment-wide fallback model. PI_DEFAULT_PROVIDER picks which key below is used. # A provider that authenticates from the host (amazon-bedrock with an ECS task, IRSA or EC2 # instance role, and AWS_REGION) needs no key: set PI_DEFAULT_CREDENTIALS=host, plus # PI_DEFAULT_PROVIDER and PI_DEFAULT_MODEL. Runs then use and are billed to those credentials. # PI_DEFAULT_CREDENTIALS=host OPENROUTER_API_KEY= ANTHROPIC_API_KEY= PI_DEFAULT_PROVIDER=openrouter # Vision-capable default for chat and computer screenshots. # Computer-use tests can override this with COMPUTER_E2E_MODEL. PI_DEFAULT_MODEL=openai/gpt-6-luna # Start spaces in the Auto approval mode instead of Ask (people can still change it). # RAKAZO_AUTO_REVIEW=1 # Optional Auto Review verifier. Default is the deployment or user LLM (no extra key). # Users choose their own approval connection, model and backups in Settings → Models. # Optional deployment default through the existing OpenRouter connection: # RAKAZO_AUTO_REVIEW_PROVIDER=openrouter # RAKAZO_AUTO_REVIEW_MODEL=typesafe/jev-1.14 # Or use TypeSafe directly instead of the LLM checker. # RAKAZO_AUTO_REVIEW_PROVIDER=jev # TYPESAFE_API_KEY= # Optional Jev model (default jev-latest) and minimum choice confidence (0-1, default 0.5). # Below the confidence floor, Auto Review asks the user. # RAKAZO_AUTO_REVIEW_MODEL=jev-latest # RAKAZO_AUTO_REVIEW_MIN_CONFIDENCE=0.5 # Optional Fish Audio speech model used when a connection does not set its own. # Default is s2.1-pro. A Fish connection can override this in Voice settings. # FISH_TTS_MODEL=s1 # Optional local OpenAI-compatible models. Leave blank to disable the provider. RAKAZO_LOCAL_MODELS= RAKAZO_LOCAL_MODELS_URL=http://127.0.0.1:11434/v1 RAKAZO_LOCAL_CONTEXT_WINDOW=32768 RAKAZO_LOCAL_MAX_TOKENS=4096 # Allow user-connected OpenAI-compatible endpoints on public hostnames (default: off). RAKAZO_OPENAI_COMPAT_ALLOW_PUBLIC= # Comma-separated exact model hostnames allowed to resolve only to private addresses. # No URLs or wildcards; metadata and link-local addresses remain blocked. RAKAZO_OPENAI_COMPAT_PRIVATE_HOSTS= # Set to 1 to let bot credentials (request_secret) target plain-HTTP origins on # private LAN hosts (10.x, 172.16-31.x, 192.168.x, 100.64-127.x, *.local, loopback). RAKAZO_SECRETS_ALLOW_PRIVATE_HTTP= # Allow remote MCP, API/GraphQL connectors, and OpenAI-compatible model and speech servers # on loopback / RFC1918 / Docker-network hosts for every user. # No app account bypasses this policy. Leave unset on public installs. # Self-hosted voice appears in settings only when this is true or # RAKAZO_OPENAI_COMPAT_ALLOW_PUBLIC=1. Its connection details are entered in the UI. MCP_ALLOW_PRIVATE_ENDPOINT= # Stdio MCP servers (off unless MCP_STDIO_ENABLED=true and the command is allowlisted). MCP_STDIO_ENABLED= # Comma-separated exact commands, for example: npx,uvx MCP_STDIO_ALLOWED_COMMANDS= # `npx ` servers are installed once here, shared by the API and worker. # Default: DATA_DIR/mcp-packages (or /data/mcp-packages), else the OS temp dir. MCP_PACKAGES_DIR= # Install timeout (default 180000), handshake timeout after launch (default 30000), and how # long an unused server process keeps running (default 900000; 0 keeps it until shutdown). MCP_STDIO_INSTALL_TIMEOUT_MS= MCP_STDIO_STARTUP_TIMEOUT_MS= MCP_STDIO_IDLE_MS= # How long a run waits for one MCP server's tool list before going on without it (default 20000). MCP_DISCOVERY_TIMEOUT_MS= E2B_API_KEY= COMPOSIO_API_KEY= # Optional integrations.sh-compatible catalog base URL (Rakazo appends api/search). # Example: https://integrations.sh/ or a self-hosted mirror base, not the full search endpoint. INTEGRATIONS_CATALOG_URL= # Optional alternative managed connector provider. PIPEDREAM_CLIENT_ID= PIPEDREAM_CLIENT_SECRET= PIPEDREAM_PROJECT_ID= PIPEDREAM_ENVIRONMENT=development # Optional messaging surface (Chat SDK). Each platform mounts when its full # credential set is present; webhooks arrive at /api/v1/messaging/webhook/. # Users link a chat app to their account from the web (Messaging settings). # Set true to instead let unknown senders auto-provision their own chat-only # accounts (their runs bill the deployment model key): MESSAGING_OPEN_SIGNUP=false # Sendblue (iMessage/SMS — all four required): SENDBLUE_API_KEY_ID= SENDBLUE_API_SECRET= SENDBLUE_SIGNING_SECRET= SENDBLUE_PHONE_NUMBER= # Slack (both required). Channels and rooms use the shared messaging team-chat # path when TEAM_CHAT_BOT_ID is set; Slack is one adapter, not a separate stack. # The bot token needs the reactions:write scope for the 👀 receipt. # Multi-workspace installs: configure the Slack app OAuth redirect as # /api/v1/messaging/install/slack/callback. No bot token is needed. SLACK_CLIENT_ID= SLACK_CLIENT_SECRET= # Single-workspace fallback: SLACK_BOT_TOKEN= SLACK_SIGNING_SECRET= # Gateway bot for provider-neutral team/external rooms (Slack, later Teams, etc.). # Alias SLACK_RAKAZO_BOT_ID is accepted for older configs. TEAM_CHAT_BOT_ID= # Optional separate judge model for ambient room replies (both or neither): TEAM_CHAT_JUDGE_PROVIDER= TEAM_CHAT_JUDGE_MODEL= # WhatsApp Business Cloud (all four required): WHATSAPP_ACCESS_TOKEN= WHATSAPP_PHONE_NUMBER_ID= WHATSAPP_APP_SECRET= WHATSAPP_VERIFY_TOKEN= # Telegram (both required). Inbound is webhook-only at # /api/v1/messaging/webhook/telegram with header X-Telegram-Bot-Api-Secret-Token; # the worker must not long-poll getUpdates. TELEGRAM_BOT_TOKEN= TELEGRAM_WEBHOOK_SECRET_TOKEN= # Extra bots: TELEGRAM_BOT_TOKEN_ + TELEGRAM_WEBHOOK_SECRET_TOKEN_ # (letters/digits). Provider: telegram-; webhook: /api/v1/messaging/webhook/telegram-. # Feishu/Lark (app id, secret, and verification token required). Inbound is # webhook-only at /api/v1/messaging/webhook/lark — do not enable long # connection in the developer console or the HTTP webhook will miss events. # Create a custom app with the Bot capability, subscribe to im.message.receive_v1, # and set the event subscription URL to that path. LARK_DOMAIN=feishu uses # open.feishu.cn (default); lark uses open.larksuite.com. Encrypt key is # optional unless event encryption is enabled in the console. LARK_APP_ID= LARK_APP_SECRET= LARK_VERIFICATION_TOKEN= LARK_ENCRYPT_KEY= LARK_DOMAIN= SUPERMEMORY_API_KEY= # Optional. Defaults to https://api.supermemory.ai. Self-hosted: http://localhost:6767 # Compose network: http://supermemory:6767 SUPERMEMORY_API_URL= # Mobile push. Set only when the Expo project enables enhanced push security. EXPO_ACCESS_TOKEN= # Optional transactional email: resend (HTTP API), smtp, or none. # Unset EMAIL_PROVIDER preserves SMTP_URL-based configuration. EMAIL_PROVIDER= EMAIL_API_KEY= SMTP_URL= EMAIL_FROM= # Local development only: capture account email without contacting a provider. EMAIL_EMULATOR= # Billing (optional; off when unset). Set both secrets together to enable model credits. # Use the same Stripe account and mode for the API key and webhook endpoint. # Webhook: /api/v1/billing/webhook; snapshot events, API 2026-09-30.endive. # Events: customer.subscription.*; customer.deleted; checkout.session.completed; # checkout.session.async_payment_succeeded; invoice.paid; invoice.payment_failed; # charge.refunded; charge.dispute.created; charge.dispute.closed. # STRIPE_SECRET_KEY=sk_test_replace-me # STRIPE_WEBHOOK_SECRET=whsec_replace-me # Optional: display the legacy seat price. Credit tiers create reusable prices automatically. # STRIPE_PRICE_ID=price_replace-me VAPID_PUBLIC_KEY= VAPID_PRIVATE_KEY= # Structured logs to stdout (json in production, pretty in development unless overridden). LOG_LEVEL=info LOG_FORMAT= # Optional Axiom ingest. Needs both token and dataset. Failures never affect the product. AXIOM_TOKEN= AXIOM_DATASET= # Optional region: AXIOM_EDGE is a hostname (eu-central-1.aws.edge.axiom.co). # AXIOM_EDGE_URL is an https URL and wins when both are set. AXIOM_EDGE= AXIOM_EDGE_URL= # Days to keep security events (sign-ins, credential changes, refusals). Default 90. SECURITY_EVENT_RETENTION_DAYS= # Error reporting is off unless a DSN is set. SENTRY_DSN= SENTRY_BROWSER_DSN= SENTRY_ENVIRONMENT= SENTRY_RELEASE= # Optional. GET /internal/health on the API port returns this as `revision` so you can confirm the deployed commit. GIT_SHA= # --- Compose production deployments --- # Absolute path of this checkout as the Docker *daemon* sees it. Production Compose defaults to # /srv/rakazo on Linux; override it for any other host path so the updater bind mount resolves. # Linux override: RAKAZO_DEPLOY_DIR=/opt/rakazo # Docker Desktop on Windows (C:\Users\you\rakazo): # RAKAZO_DEPLOY_DIR=/run/desktop/mnt/host/c/Users/you/rakazo RAKAZO_DEPLOY_DIR= # Compose files the updater reconciles, in overlay order, separated like Compose's own # COMPOSE_FILE (":" unless COMPOSE_PATH_SEPARATOR says otherwise). Leave unset for the base stack. # RAKAZO_COMPOSE_FILE=infra/compose/docker-compose.prod.yml:ops/compose/overlay.yml # Docker sandboxes on the prod stack (instead of a remote provider) layer # infra/compose/docker-compose.prod.docker.yml — list it here too: # RAKAZO_COMPOSE_FILE=infra/compose/docker-compose.prod.yml:infra/compose/docker-compose.prod.docker.yml RAKAZO_COMPOSE_FILE= # Extra services an update pulls, recreates and rolls back, comma separated. Name any overlay # service built from the application image, or it keeps running the previous code after an update. # Appended to api, worker, web; the updater itself is refused. # RAKAZO_UPDATE_SERVICES=supervisor RAKAZO_UPDATE_SERVICES= # Published images (defaults match this repository). Tag `local` is built from the checkout. RAKAZO_IMAGE=ghcr.io/elie222/rakazo/app RAKAZO_IMAGE_TAG=local RAKAZO_IMAGE_TAG_PREVIOUS= RAKAZO_UPDATER_IMAGE=ghcr.io/elie222/rakazo/updater RAKAZO_UPDATER_IMAGE_TAG=local # Required only when starting the opt-in `updater` Compose profile; the sidecar refuses to start # without it. Use a dedicated random value, not BETTER_AUTH_SECRET, # SANDBOX_SUPERVISOR_TOKEN, or SCREEN_PROXY_SECRET; # ≥32 chars in production. Leave empty when the sidecar is disabled. RAKAZO_UPDATER_TOKEN= # Optional default UI locale for the web SPA (en | de | ko | tr | hi | pt-BR | zh-CN). # Overridden by localStorage key rakazo.uiLocale when the user picks a language in Settings. # VITE_DEFAULT_UI_LOCALE=en # Expo: English, Simplified Chinese, Russian, or German (en | zh-CN | ru | de). # Overridden by SecureStore key rakazo.uiLocale. Account → Language offers English # and Simplified Chinese; the other catalogs follow this default or the device language. # EXPO_PUBLIC_DEFAULT_UI_LOCALE=en # Optional bot media generation. Models must be explicitly enabled. MEDIA_GENERATION_PROVIDER=disabled MEDIA_GENERATION_BASE_URL=https://queue.fal.run MEDIA_GENERATION_API_KEY= MEDIA_GENERATION_IMAGE_MODEL= MEDIA_GENERATION_VIDEO_MODEL= # Optional content-free product analytics (API and worker). Off unless selected. ANALYTICS_PROVIDER=none ANALYTICS_KEY= # Generate once (openssl rand -hex 32); share between API and worker and retain on token rotation. # Error reports also use it to count affected users by a hashed id. ANALYTICS_PSEUDONYM_SECRET= ANALYTICS_HOST=https://us.i.posthog.com