Skip to main content

Environment Variables

This page lists the environment variables read by the current Libre WebUI backend, frontend, and maintenance scripts.

Backend Server

VariableDefaultPurpose
NODE_ENVdevelopmentRuntime mode
PORT3001 in dev, 8080 in productionBackend HTTP port
TRUST_PROXYunsetExpress trust proxy setting
CORS_ORIGINlocal dev originsComma-separated allowed browser origins
SERVE_FRONTENDunsetServe built frontend from backend when true
DOCKER_ENVunsetEnables Docker-oriented behavior when true
DATA_DIRbackend/dataPersistent data directory
PLUGINS_DIR$DATA_DIR/plugins, otherwise plugins/Writable directory for installed/customized plugins
BASE_URLhttp://localhost:3001Base URL used for OAuth callback defaults
LOG_LEVELinfo (warn in tests)Backend log level

Authentication and Security

VariableDefaultPurpose
ENABLE_SIGNUPfalseAllow registration after the first local administrator
JWT_SECRETgenerated/fallback in developmentJWT signing secret; set explicitly in production
JWT_EXPIRES_IN7dSession-token lifetime
ENCRYPTION_KEYauto-generated64-character hex key for encrypted values
DEBUG_ENCRYPTIONunsetLogs encryption debug output when set
TURNSTILE_SITE_KEYunsetCloudflare Turnstile site key for login and signup
TURNSTILE_SECRET_KEYunsetCloudflare Turnstile secret key for backend verification
TURNSTILE_EXPECTED_HOSTNAMEhostname from BASE_URLRequired hostname in Cloudflare's verification response

Turnstile is enabled only when both Turnstile keys are present.

ENABLE_SIGNUP=false still permits the first local administrator on an empty database, then blocks additional local and OAuth accounts. Protect a remotely reachable bootstrap route with an outer identity boundary before first start.

Chat WebSocket admission can be tuned without weakening authentication:

VariableDefaultPurpose
CHAT_WS_MAX_PAYLOAD_BYTES10 MiBMaximum accepted WebSocket message size
CHAT_WS_MAX_MESSAGES_PER_MINUTE120Per-connection WebSocket message ceiling

OAuth

VariablePurpose
GITHUB_CLIENT_IDGitHub OAuth client ID
GITHUB_CLIENT_SECRETGitHub OAuth client secret
GITHUB_CALLBACK_URLGitHub callback URL override
HUGGINGFACE_CLIENT_IDHugging Face OAuth client ID
HUGGINGFACE_CLIENT_SECRETHugging Face OAuth client secret
HUGGINGFACE_CALLBACK_URLHugging Face callback URL override

If callback URLs are not set, Libre WebUI builds defaults from BASE_URL.

Ollama

VariableDefaultPurpose
OLLAMA_BASE_URLhttp://localhost:11434Ollama API base URL
OLLAMA_TIMEOUT300000Standard Ollama request timeout in milliseconds
OLLAMA_LONG_OPERATION_TIMEOUT900000Long operation timeout for pulls and large requests

Libre Claw

VariableDefaultPurpose
LIBRE_CLAW_BASE_URLhttp://127.0.0.1:8766Optional Libre Claw daemon URL
LIBRE_CLAW_TIMEOUT_MS30000Libre Claw HTTP request timeout

Work Runtime

These variables configure native Work execution on the machine running the Libre WebUI backend:

VariableDefaultPurpose
WORK_RUNTIME_IMAGEnode:22.22-bookworm@sha256:2d178f2785b96dfbf62a416ca2e40f50e30150b4ff3320d706f0d96e90600eb3Pinned image used for Work task containers
WORK_DOCKER_COMMANDdockerDocker CLI executable available to the backend process
WORK_COMMAND_TIMEOUT_MS120000Default timeout; a tool can request up to 600000 ms
WORK_MAX_OUTPUT_CHARS50000Captured stdout/stderr limit, applied to each stream
WORK_MAX_AGENT_ROUNDS48Provider-agnostic model/tool round budget for one run
WORK_MEMORY_LIMIT2gMemory limit passed to each Work container
WORK_CPU_LIMIT2CPU limit passed to each Work container
WORK_PIDS_LIMIT256Process limit passed to each Work container
WORK_PREVIEW_PORT4173Port a preview server must use inside the task container
WORK_PREVIEW_BIND127.0.0.1Host interface a task preview port is published on
WORK_MAX_ACTIVE_RUNTIMES_GLOBAL3Concurrent container-backed tasks for the whole instance
WORK_MAX_ACTIVE_RUNTIMES_PER_USER2Concurrent container-backed tasks for one administrator
WORK_MAX_TASKS_GLOBAL500Maximum persisted Work tasks for the whole instance
WORK_MAX_TASKS_PER_USER100Maximum persisted Work tasks for one administrator
WORK_NETWORK_NAMElibre-webui-workManaged sandbox bridge network for networked tasks
WORK_RUNTIME_DNSunsetComma-separated resolver IPs forced onto networked tasks
WORK_DOCKER_SOCKETDOCKER_HOST if unix://, else /var/run/docker.sockDocker Engine socket for terminals and diagnostics
WORK_TERMINAL_MAX_SESSIONS_PER_TASK2Simultaneous browser terminals attached to one task
WORK_TERMINAL_IDLE_TIMEOUT_MS900000Idle timeout before a terminal session is closed
WORK_HOST_WORKSPACES_ENABLEDfalseAllow a task to use a host folder instead of a volume
WORK_HOST_WORKSPACE_ROOTSthe server user's home directory:-separated roots a host workspace must live inside
AGENT_CLI_MODELS_ENABLEDtrueOffer installed agent CLIs as chat models to admins
AGENT_CLI_TIMEOUT_MS600000Time an agent CLI may run before it is killed
CODEX_OAUTH_MODELS_ENABLEDtrueOffer the Codex (ChatGPT) provider to admins
CODEX_HOME~/.codexWhere the Codex CLI sign-in (auth.json) is read from

A host workspace bind-mounts a real directory at /workspace, so the task can read and write those files directly instead of working in its own Docker volume. That is a deliberate reduction of the sandbox: keep WORK_HOST_WORKSPACES_ENABLED off unless you want it, and keep WORK_HOST_WORKSPACE_ROOTS as narrow as possible. Requested paths are resolved through symlinks before they are checked against the roots, and folders such as .ssh, .gnupg, .aws, and .config are rejected outright.

Agent CLI models expose coding agents already installed on the server (claude, codex) as selectable chat models, so a subscription agent can answer without an API key. Only administrators see them, the CLI runs as the Libre WebUI server user, and it inherits that user's agent credentials — treat it as equivalent to granting shell access to those agents.

Networked Work tasks attach to the managed WORK_NETWORK_NAME bridge, created with inter-container communication disabled so one sandbox cannot reach another sandbox or the deployment's own containers. WORK_RUNTIME_DNS is the supported egress-policy hook: point it at a filtering resolver to apply name-based allow/deny lists. Entries that are not IPv4/IPv6 addresses are rejected and logged. DNS filtering does not constrain direct-IP egress; add host firewall rules when a deployment requires that.

The interactive terminal needs the Docker Engine Unix socket. When DOCKER_HOST points at a remote TCP endpoint and WORK_DOCKER_SOCKET is unset, Libre WebUI reports the terminal as unavailable and the rest of Work continues to run.

Work reads these values when the backend starts. The preview port is internal to the task container; Libre WebUI publishes it to a dynamically assigned loopback port rather than exposing this value directly on every host interface.

Keep the runtime image pinned to a reviewed version or digest. Increasing concurrency or resource limits raises the amount of Docker-host capacity one or more autonomous runs can consume. WORK_MAX_AGENT_ROUNDS applies equally to Ollama and plugin-backed runs; there is no lower plugin-only clamp. The tool-call safety budget is max(128, WORK_MAX_AGENT_ROUNDS × 8). When a run uses its round budget, Work requests a final no-tools handoff from the model and ends in the terminal needs_input state instead of returning a raw round-limit error or claiming successful completion. A follow-up run continues in the same durable workspace. Persisted tool output has a separate bound of approximately 20,000 source characters plus a truncation marker.

These variables tune a Work runtime that is already reachable. Repository Compose deployments enable it by default: the image ships the Docker CLI and the Compose files mount the host Docker socket. Two Compose-level variables control that wiring:

VariableDefaultPurpose
DOCKER_GID0Group id of the host Docker socket, added to the container user
DOCKER_SOCKET/var/run/docker.sockHost path of the Docker socket to mount

DOCKER_GID must be the socket's group as seen inside a container; a macOS host reports a different value. The Helm chart mounts no runtime socket, so Work remains unavailable on Kubernetes.

Repository Compose files also accept WEBUI_BIND_ADDRESS (default 127.0.0.1) and WEBUI_PORT (default 8080). Keep the loopback default unless a trusted LAN or host reverse proxy must reach the port.

Provider Model Discovery

A provider's model catalog is rediscovered on its own when it is missing or stale, so a reload reflects the models the provider currently serves. These variables tune that cycle:

VariableDefaultPurpose
PLUGIN_MODEL_DISCOVERY_TTL_MS21600000 (6 h)Age at which a stored catalog is refreshed on the next plugin-list read
PLUGIN_MODEL_DISCOVERY_RETRY_MS600000 (10 min)Minimum gap between attempts, so a failing provider is not probed often
PLUGIN_MODEL_DISCOVERY_REFRESH_DEADLINE_MS3000How long a plugin-list response waits for refreshes before answering

A refresh that outruns the deadline still completes and is served on the next request. An explicit Refresh models always contacts the provider and ignores the interval.

Provider Plugin Keys

Provider plugins can use environment keys as deployment-wide defaults:

VariableProvider
OPENAI_API_KEYOpenAI and OpenAI TTS
ANTHROPIC_API_KEYAnthropic
GROQ_API_KEYGroq
GEMINI_API_KEYGoogle Gemini
MISTRAL_API_KEYMistral
OPENROUTER_API_KEYOpenRouter
KIMI_API_KEYKimi Code by Moonshot AI
GITHUB_API_KEYGitHub Models
HUGGINGFACE_API_KEYHugging Face APIs where configured
ELEVENLABS_API_KEYElevenLabs TTS
COMFYUI_API_KEYComfyUI deployments that require an API key

Users can also store provider credentials in the UI when per-user keys are preferred. Environment keys are used only with the routing and authentication projection of an unshadowed bundled definition. Imported definitions, writable definitions that reuse a bundled ID, and administrator-saved custom routes require a credential stored by that account. Libre WebUI will not attach an environment key to those routes or expose it through discovery and availability checks. Trust comes from a compiled hash of each shipped manifest, so container layouts where the legacy and bundled plugin directories share a path remain supported without treating a modified manifest as bundled.

User-saved keys are bound to the effective provider definition, source, authentication contract, and routing values. Users must save a key again after an administrator changes that destination. Pre-upgrade unbound keys are accepted and bound on first use only for an exact shipped definition using its bundled route.

Frontend

VariableDefaultPurpose
VITE_API_BASE_URLinferred from host/dev configFrontend API base URL
VITE_WS_BASE_URLinferred from API URLWebSocket base URL
VITE_APP_VERSIONpackage version injected by Vite configDisplayed app version
VITE_DEMO_MODEfalseEnables demo-mode mocks when true
VITE_API_TIMEOUT300000Frontend API timeout in milliseconds
VITE_BACKEND_URLhttp://localhost:3001Used by some auth helper components
VITE_DEBUG_VERBOSEunsetEnables verbose frontend debug logs in development
VITE_LOG_LEVELunsetOverrides the frontend log level
ELECTRON_BUILDunsetEnables Electron-specific Vite behavior when true

Maintenance Scripts

VariablePurpose
CHANGELOG_AISet to 0 to disable AI-assisted changelog drafts
CHANGELOG_AI_MODELOllama model for release/changelog generation
CHANGELOG_AI_TIMEOUT_MSTimeout for AI changelog generation in milliseconds

Example:

CHANGELOG_AI_MODEL=glm-5.2:cloud npm run changelog
CHANGELOG_AI=0 npm run release:minor

Production Example

NODE_ENV=production
PORT=3001
SERVE_FRONTEND=true
DATA_DIR=/data/libre-webui
CORS_ORIGIN=https://librewebui.example
BASE_URL=https://librewebui.example

JWT_SECRET=replace-with-a-long-random-secret
ENCRYPTION_KEY=replace-with-64-hex-characters
ENABLE_SIGNUP=false

OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_TIMEOUT=300000
OLLAMA_LONG_OPERATION_TIMEOUT=900000

TURNSTILE_SITE_KEY=...
TURNSTILE_SECRET_KEY=...
TURNSTILE_EXPECTED_HOSTNAME=librewebui.example