Environment Variables
This page lists environment variables for self-hosted Windshift. Most variables have CLI flag equivalents in Configuration Options.
Required values
| Variable | Required? | Description |
|---|---|---|
SSO_SECRET |
Yes | Session-cookie and SSO-state signing/encryption secret. Generate once with openssl rand -hex 32 and keep it stable. |
BASE_URL |
Strongly recommended | Public URL users access Windshift from. Required for correct links, SSO redirects, WebAuthn, calendar feeds, and runners. |
Windshift accepts SESSION_SECRET as a legacy fallback when SSO_SECRET is unset. New deployments should use SSO_SECRET.
HTTP and reverse proxy
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP server port inside the container/process. |
BASE_URL |
- | Public URL, for example https://windshift.example.com or https://example.com/windshift. |
WINDSHIFT_CONTEXT_PATH |
- | Optional subpath such as /windshift when serving below a domain root. Set BASE_URL to the full subpath URL to match. |
ALLOWED_HOSTS |
derived from BASE_URL |
Comma-separated browser origins for CORS, CSRF, WebAuthn, and SSO redirect validation. This is not a Host-header request filter. Leave unset for a single-domain deployment so Windshift derives the origin from BASE_URL; an explicit value overrides that derivation. |
FORM_EMBED_ORIGINS |
- | Comma-separated origins permitted to embed public forms. |
USE_PROXY |
false |
Trust forwarded protocol/client-IP headers from reverse proxies. |
ALLOW_INSECURE_HTTP |
false |
Allow browser access via plain http on non-localhost origins. Trusted LANs and testing only. |
ADDITIONAL_PROXIES |
- | Additional trusted proxy IPs, comma-separated. |
DISABLE_IP_RATE_LIMIT |
false |
Disable IP-based rate limiting. Use only behind trusted controls. |
When USE_PROXY=true, ensure Windshift is reachable only from your reverse proxy. Forwarded headers are security-sensitive.
By default, a plain-HTTP BASE_URL works only for localhost. Any other HTTP hostname or IP fails at startup with Failed to create CORS middleware ... insecure origin patterns. Serve HTTPS instead. On a trusted LAN, set ALLOW_INSECURE_HTTP=true. See Docker for options.
Secrets, auth, and WebAuthn
| Variable | Default | Description |
|---|---|---|
SSO_SECRET |
required | Preferred session and SSO secret. |
SESSION_SECRET |
- | Legacy fallback if SSO_SECRET is unset. |
ENABLE_ADMIN_FALLBACK |
false |
Enable password-based admin fallback when SSO is restrictive or unavailable. |
RECOVER_USER |
- | Emergency recovery helper for user access flows. |
SESSION_VALIDATION_CACHE_TTL |
5s |
How long session-validation results are cached. Accepts a Go duration such as 5s. |
WEBAUTHN_RP_ID |
host name | WebAuthn relying-party ID, usually your public hostname. |
WEBAUTHN_RP_NAME |
Windshift |
Display name shown by authenticators. |
Database
| Variable | Default | Description |
|---|---|---|
DB_PATH |
windshift.db |
SQLite database file path. |
POSTGRES_CONNECTION_STRING |
- | PostgreSQL connection string. If set, PostgreSQL is used instead of SQLite. |
DB_TYPE |
- | Set to postgres to build a connection string from the POSTGRES_* variables. |
POSTGRES_HOST |
postgres |
Host for generated PostgreSQL connection strings. |
POSTGRES_PORT |
5432 |
Port for generated PostgreSQL connection strings. |
POSTGRES_USER |
windshift |
User for generated PostgreSQL connection strings. |
POSTGRES_PASSWORD |
- | Password for generated PostgreSQL connection strings. |
POSTGRES_DB |
windshift |
Database name for generated PostgreSQL connection strings. |
POSTGRES_SSLMODE |
disable |
TLS mode for a connection built from the split POSTGRES_* variables: disable, allow, prefer, require, verify-ca, or verify-full. Use require or stricter for remote or managed PostgreSQL. Invalid values fail startup. |
MAX_READ_CONNS |
30 |
Read connection pool size. On SQLite, it caps concurrent readers. On PostgreSQL, it sizes the pool: maximum open equals this value and maximum idle equals half. Keep it below PostgreSQL max_connections. |
MAX_WRITE_CONNS |
1 |
SQLite write connection pool size. |
POSTGRES_REPLICA_COUNT |
1 |
Number of Windshift replicas sharing PostgreSQL, used to validate the aggregate connection budget. |
POSTGRES_CONNECTION_HEADROOM |
10 |
PostgreSQL connections reserved for migrations, administration, and other clients when validating the connection budget. |
DB_REQUEST_TIMEOUT |
12s |
Maximum database-work duration for normal HTTP requests. Accepts a Go duration such as 12s or 1m. |
MAX_USER_CONCURRENCY |
16 |
Maximum simultaneous in-flight /api requests per authenticated user. A burst from one user (or one agent) cannot exhaust the database. 0 disables the cap. |
Recommended production form:
POSTGRES_CONNECTION_STRING=postgres://windshift:secret@postgres:5432/windshift?sslmode=disableDocker Compose-friendly form:
DB_TYPE=postgres
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_USER=windshift
POSTGRES_PASSWORD=secret
POSTGRES_DB=windshift
# `disable` is suitable only for the bundled PostgreSQL container on the same Docker network.
# Use `require`, `verify-ca`, or `verify-full` for remote or managed PostgreSQL.
POSTGRES_SSLMODE=disableFiles
| Variable | Default | Description |
|---|---|---|
ATTACHMENT_PATH |
- | Directory for uploaded file attachments. Use a persistent volume in Docker. |
SSH TUI and MCP
| Variable | Default | Description |
|---|---|---|
SSH_ENABLED |
false |
Enable the SSH TUI server. |
SSH_PORT |
23234 |
SSH server port. |
SSH_HOST |
localhost |
SSH server bind address. |
MCP_ENABLED |
false |
Enable the MCP server at /mcp. |
Logging
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL |
info |
debug, info, warn, or error. |
LOG_FORMAT |
text |
text, json, or logfmt. Use json for most container log pipelines. |
Plugins
| Variable | Default | Description |
|---|---|---|
DISABLE_PLUGINS |
false |
Disable the plugin system entirely. |
PLUGIN_DIR |
- | Primary plugin directory. |
PLUGIN_DIRS |
- | Additional plugin directories, comma-separated. |
Private network egress
| Variable | Default | Description |
|---|---|---|
ALLOW_LOCAL_CONNECTIONS |
false |
Allow server-side HTTP clients (SCM, Jira, LLM, OIDC, webhooks) to reach loopback and private addresses. |
By default, Windshift blocks server-side outbound HTTP to private and non-public addresses. This reduces SSRF risk. Enable this switch when Windshift must reach an internal endpoint, such as a private identity provider, self-hosted SCM, or local LLM server:
ALLOW_LOCAL_CONNECTIONS=trueThis is a global switch. Enable it only when sensitive internal endpoints, such as cloud metadata services and admin panels, are not reachable from the Windshift host. Windshift ignores the removed OIDC_ALLOWED_PRIVATE_CIDRS and LLM_ALLOWED_PRIVATE_CIDRS variables.
AI and LLM
| Variable | Default | Description |
|---|---|---|
LLM_PROVIDERS_FILE |
- | Path to a custom LLM provider catalog JSON file. |
AI_PROMPTS_DIR |
/data/prompts in Docker |
Directory for custom AI prompt overrides. |
LLM_ENDPOINT |
- | Legacy/fallback OpenAI-compatible inference endpoint. Prefer AI Connections in the admin UI. |
Public AI providers work without extra configuration. Local and internal models, such as Ollama, LM Studio, and internal gateways, require ALLOW_LOCAL_CONNECTIONS=true.
Then create a Local / Custom AI connection. Use the base URL that Windshift can reach, such as http://localhost:11434/v1, http://host.docker.internal:11434/v1, or http://172.17.0.1:11434/v1.
Coding agent runner
The coding-agent runner is opt-in. See Coding Agent Runner before enabling these.
| Variable | Default | Description |
|---|---|---|
CODING_AGENT_ENABLED |
false |
Set to true to enable the coding-agent system. The Windshift server then runs as an orchestrator only: it dispatches runs but executes no agent containers itself. |
CODING_AGENT_WS_API_URL |
BASE_URL + /api |
API URL agent containers use to reach Windshift. Override when BASE_URL is not reachable from containers (for example a localhost URL). Must end in /api. |
These are the only CODING_AGENT_* settings the server reads. Agent containers run on windshift-runner hosts. Configure those hosts with WSRUNNER_* variables in the runner process, not the Windshift server process. Configure the agent image, Docker binary, worktree and cache location, and concurrency on the runner. See Coding Agent Runner for the runner Compose file and the full WSRUNNER_* table.
Notifications, Jira, and sidecars
| Variable | Default | Description |
|---|---|---|
VAPID_PUBLIC_KEY |
auto-generated | Web Push (VAPID) public key. Without an explicit pair, Windshift generates one on first boot, stores it in system settings, and enables push notifications. Set it with VAPID_PRIVATE_KEY only to manage or rotate the key pair deliberately. |
VAPID_PRIVATE_KEY |
auto-generated | Web Push (VAPID) private key. Set it with VAPID_PUBLIC_KEY when you provide a managed pair. Rotating either key invalidates existing push subscriptions. Users must subscribe again. |
VAPID_SUBJECT |
BASE_URL |
Contact URI or mailto: for the push subscription, sent to push services. |
NOTIFICATION_FLUSH_INTERVAL |
built-in | Notification write-batcher flush interval, as a Go duration (5s, 1m). |
NOTIFICATION_BATCH_SIZE |
built-in | Notification write-batcher batch size. |
NOTIFICATION_SYNC_INTERVAL |
built-in | Notification synchronization interval. |
WINDSHIFT_NOTIFICATION_BATCH_INTERVAL |
built-in | Email notification batch scheduler cadence. |
JIRA_CAPTURE_PAYLOADS |
- | Directory for Jira import request/response payload debugging. |
LOGBOOK_ENDPOINT |
- | URL of a Logbook sidecar service, if used. |
Docker Compose .env template
# Required
DOMAIN=windshift.example.com
BASE_URL=https://windshift.example.com
SSO_SECRET=replace-with-openssl-rand-hex-32
# HTTP
PORT=8080
ALLOWED_HOSTS=windshift.example.com
USE_PROXY=true
# Storage
ATTACHMENT_PATH=/data/attachments
# PostgreSQL
POSTGRES_PASSWORD=replace-with-a-strong-password
POSTGRES_CONNECTION_STRING=postgres://windshift:${POSTGRES_PASSWORD}@postgres:5432/windshift?sslmode=disable
# Traefik / ACME
LETSENCRYPT_EMAIL=admin@example.com
# Optional: allow egress to private/loopback endpoints (local LLM, internal IdP/SCM)
# ALLOW_LOCAL_CONNECTIONS=trueUsing Varlock for configuration management
Varlock is an optional CLI tool that adds schema-based validation and secret leak prevention to .env files. It works as a drop-in wrapper.
Install
# macOS
brew install dmno-dev/tap/varlock
# Linux / CI
curl -sSfL https://varlock.dev/install.sh | sh -sInitialize
cd /path/to/windshift
varlock initExample .env.schema
# @required @sensitive @type=string
SSO_SECRET=
# @required @type=url
# @example="https://windshift.example.com"
BASE_URL=
# @type=port @optional
PORT=8080
# @sensitive @optional
POSTGRES_PASSWORD=
# @optional @type=email
LETSENCRYPT_EMAIL=
# @optional @type=boolean
# Opens private/loopback egress for all server-side HTTP clients.
ALLOW_LOCAL_CONNECTIONS=Validate
varlock loadRun with validation
varlock run -- docker compose up -d