Skip to content

Backend environment

All backend configuration is via environment variables. The shipped .env.example is the fully-commented source of truth; this page organises it.

VariableDefaultDescription
TMDB_API_KEYTMDB Read Access Token (v4) or legacy key. The one mandatory secret.
VariableDefaultDescription
DATABASE_URLFull PostgreSQL URL; takes precedence over the parts below.
POSTGRES_HOST / POSTGRES_PORT / POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORDlocalhost / 5432 / crimson ×3Used to assemble the connection when DATABASE_URL is unset.
DB_POOL_MIN / DB_POOL_MAX1 / 10Connection-pool sizing per replica.
DB_CONNECT_TIMEOUT30Seconds to wait at startup for the database.
DB_PREPARE_THRESHOLDunset (off)Server-side prepared statements. Leave off behind a transaction-mode PgBouncer.
VariableDefaultDescription
REQUIRE_LOGINtrueSite-wide members-only wall. false reopens the whole API.
SIGNUP_INVITE_CODEReusable invite code(s), comma-separated, gating both account types. Empty ⇒ signups closed (403).
ADMIN_EMAILSComma-separated emails promoted to admin on startup.
FRONTEND_BASE_URLhttps://crimsonhaven.toOrigin used to build emailed verify/reset links.
SECURITY_EVENTS_RETENTION_DAYS90How long the security ledger (Admin › Security: auth denials, rate-limit trips, admin actions) keeps events before the housekeeping sweep prunes them.

See Accounts & the login wall for the full model.

Only needed for email + password accounts. Unset SMTP_HOST disables sending (registration still works; mail no-ops).

VariableDefaultDescription
SMTP_HOSTMail server host; unset disables email.
SMTP_PORT587Mail server port.
SMTP_SECURITYstarttlsstarttls | ssl | none.
SMTP_USER / SMTP_PASSWORDCredentials.
SMTP_FROM / SMTP_FROM_NAMEEnvelope + display sender.
VariableDefaultDescription
PROXY_SECRETrandom per-processHMAC secret shared with crimson-proxy. Signs /sign links, the subtitle proxy and cache tickets. Must be stable + identical across replicas and equal to each proxy’s NITRO_PROXY_SECRET. openssl rand -hex 32.
CRIMSON_PROXY_BASEComma-separated edge proxy origin(s). Enables the /sign grant. Unset ⇒ /sign returns 503 and clients use the extension/backend.
VariableDefaultDescription
JELLYFIN_URL / JELLYFIN_USERNAME / JELLYFIN_PASSWORDEnable the Jellyfin source (your own server, reachable from the backend).
JELLYFIN_EDGE_INJECToffDeliver Jellyfin via the proxy edge (token injected at the edge) instead of the backend proxy. Requires the proxy’s NITRO_JELLYFIN_*.
RUN_CACHE_WORKERtrueRun the background ffmpeg cache downloader on this replica. Set true on one dedicated worker only.
CACHE_INTERNAL_BASE / CACHE_MAX_CONCURRENT / CACHE_DOWNLOAD_TIMEOUT / CACHE_MIN_FREE_BYTES / CACHE_QUEUE_MAXsee .env.exampleCache downloader tuning.

See Operator-owned sources for setup.

The reading surface is on by default and needs no API key — discovery is AniList, and chapters/pages resolve in the viewer’s browser. These are plain preferences (they name no host); the last two are read only by an optional server-side provider.

VariableDefaultDescription
MANGA_ENABLEDtrueMaster switch for the whole reading surface. false ⇒ the manga routes 503 and the client hides the row / search / reader.
MANGA_LANGUAGESenPreferred chapter language(s), comma-separated; first is the default. Handed to the browser so its resolution matches.
MANGA_CONTENT_RATINGsafe,suggestive,eroticaContent ratings to include, comma-separated. Add pornographic to include it (off by default).
MANGADEX_APP_NAMECrimsonHaven/1.0Provider-only. Descriptive User-Agent for the optional server-side provider.
MANGA_PROXY_SECRETfalls back to PROXY_SECRETProvider-only. Signs /manga_proxy image links. Reuse PROXY_SECRET.

See The reading surface (manga) for the full picture.

There is nothing to switch on — the browsable local library follows the Local source (enable one in the admin dashboard). The only related variable is optional:

VariableDefaultDescription
LOCAL_PROXY_SECRETfalls back to PROXY_SECRETSigns the public /local_art poster image links. Reuse PROXY_SECRET (stable + identical across replicas); override only if you must.

See The local media library for the full picture, and Operator-owned sources for the Local source itself.

The Live TV surface is on by default and needs no API key — the catalogue is the iptv-org public index, fetched twice daily into memory (no database table). Playback is direct-first; the signed /iptv_proxy carries only what the browser’s own rules won’t allow.

VariableDefaultDescription
IPTV_ENABLEDtrueMaster switch for the whole Live TV surface. false ⇒ the IPTV routes 503 and the client hides the nav entry and routes.
IPTV_REFRESH_HOURS12Hours between catalogue refreshes (upstream publishes daily).
IPTV_INCLUDE_NSFWfalseInclude NSFW-flagged channels in the catalogue.
IPTV_PROXY_SECRETfalls back to PROXY_SECRETSigns /iptv_proxy stream links. Reuse PROXY_SECRET (stable + identical across replicas); override only if you must.

See The Live TV surface (IPTV) for the full picture.

Optional, asleep by default. Only the provider keys are environment variables; the master switch, provider, model, budgets and the per-account grants are operator state in PostgreSQL, managed from Admin › Lumi and Admin › Users, so none of it needs a redeploy. Keys stay out of the database on purpose, so a dump of your accounts never carries billable credentials.

VariableDefaultDescription
ANTHROPIC_API_KEYunsetClaude. The recommended provider (best at persona fidelity and tool accuracy).
GEMINI_API_KEYunsetGoogle AI Studio. GOOGLE_API_KEY is accepted as an alias.

Setting a key does not switch the feature on, and switching it on does not give anyone access: both are separate, audited decisions in the dashboard.

See Lumi, the chatbot for the full picture.

VariableDefaultDescription
RUN_DB_SYNCtrueRun the periodic Fribb mapping resync. Exactly one replica should have this true.
ALLOWED_ORIGINSbuilt-in listComma-separated CORS origins. Lock down in production.
RATE_LIMIT_STORAGE_URImemory://Rate-limit backend; redis://… to share limits across replicas.
FORWARDED_ALLOW_IPSTrusted proxy IPs uvicorn honours X-Forwarded-* from. Usually * behind a reverse proxy.
METADATA_REFRESH_* / RUN_METADATA_BACKFILL / METADATA_BACKFILL_PAGESsee .env.exampleNon-anime metadata maintenance (pinned to the sync replica).

Optional integrations (each self-disables when unset)

Section titled “Optional integrations (each self-disables when unset)”
Variable(s)Feature
DISCORD_BOT_TOKEN / DISCORD_OWNER_ID / DISCORD_COMMAND_PREFIXThe Discord invite bot (python -m discord_bot).
KOFI_VERIFICATION_TOKEN / KOFI_ACTIVE_WINDOW_DAYS / KOFI_LIST_CACHE_TTLKo-fi supporters list (/supporters).
GITHUB_TOKEN / GITHUB_REPO / CHANGELOG_*Public changelog from GitHub Releases (/changelog).
OPENSUBTITLES_API_KEY / OPENSUBTITLES_APP_NAME / SUBTITLES_*OpenSubtitles player tracks (/subtitles).
HEALTH_CANARY_*The admin Source-Health probe target.
DEBUGWhen truthy, includes exception detail in 500 responses. Leave unset in production.