Configuration
Lector is configured entirely through environment variables — nothing is baked into the image. Variables are read at container start, so changing one is: edit, docker compose up -d.
Core
| Variable | Default | Description |
|---|---|---|
NODE_ENV | production | Set to production for deployed instances |
API_URL | http://localhost:3457 | Origin the browser uses to reach the API (the UI calls it directly). Set to your access host on port 3457, e.g. http://your-server:3457, or your reverse-proxy origin https://lector.home.yourdomain.com. The default only works when browsing from the server itself. |
GOOGLE_CLOUD_API_KEY | — | Optional. Google Cloud API key for text-to-speech pronunciation. |
AI translation
| Variable | Default | Description |
|---|---|---|
LLM_PROVIDER | anthropic | AI provider for translations: anthropic or openai (any OpenAI-compatible server) |
ANTHROPIC_API_KEY | — | Claude API key (only needed when LLM_PROVIDER=anthropic) |
CLAUDE_CODE_OAUTH_TOKEN | — | OAuth token for Pro/Team plan credits (alternative to API key, slower startup) |
OPENAI_COMPAT_URL | — | Base URL of your OpenAI-compatible server, e.g. http://localhost:1234 (LM Studio) or http://localhost:11434 (Ollama). Used when LLM_PROVIDER=openai. |
OPENAI_COMPAT_MODEL | — | Model id to request from that server |
OPENAI_COMPAT_API_KEY | — | Optional. Bearer token, only for authenticated endpoints |
OLLAMA_URL / LMSTUDIO_URL / APFEL_URL | — | Legacy. Still read as fallbacks for the OpenAI-compatible endpoint so existing deployments keep working. |
Multi-user accounts & OIDC
Off by default — a plain install is single-user with no login. See the Multi-user & OIDC guide for the walkthrough.
| Variable | Default | Description |
|---|---|---|
LECTOR_MODE | selfhost | Set to cloud to turn on accounts: login/register pages, sessions, per-user libraries. |
BETTER_AUTH_SECRET | — | Required in cloud mode (refuses to boot without it). Session-signing secret — generate with openssl rand -base64 32. |
BETTER_AUTH_URL | — | The public origin auth links and OAuth callbacks are minted against, e.g. https://lector.home.yourdomain.com. |
OIDC_ISSUER | — | BYO OIDC: your identity provider's issuer origin (or a pasted discovery URL). Needs all three OIDC_* credentials. v3.2.0+. |
OIDC_CLIENT_ID / OIDC_CLIENT_SECRET | — | The OAuth client you register on the IdP for Lector. |
OIDC_PROVIDER_NAME | SSO | Label for the login button ("Continue with <name>"). |
OIDC_SCOPES | openid profile email | Override the requested scopes (space- or comma-separated). |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | — | Optional; enables "Continue with GitHub". |
RESEND_API_KEY (+ EMAIL_FROM) | — | Email delivery for verification and password-reset links (the sending domain must be verified with Resend). Without it, emails land in the server log. |
TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY | — | Optional; Cloudflare Turnstile bot protection on sign-up/sign-in/reset (set both or neither). Mostly for internet-exposed instances. |
Full Docker Compose example
A complete single-user example with the common options. For the ${VAR} / .env pattern, see Compose + env vars.
services:
lector:
image: ghcr.io/heuwels/lector:${LECTOR_VERSION:-latest}
container_name: lector
restart: unless-stopped
ports:
- "3400:3000"
- "3457:3457"
volumes:
- ./data:/app/data
environment:
- NODE_ENV=production
- API_URL=http://your-server:3457
- LLM_PROVIDER=${LLM_PROVIDER:-anthropic}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- OPENAI_COMPAT_URL=${OPENAI_COMPAT_URL}
- OPENAI_COMPAT_MODEL=${OPENAI_COMPAT_MODEL}
- GOOGLE_CLOUD_API_KEY=${GOOGLE_CLOUD_API_KEY}