Environment Variables
This page is the environment-variable reference for self-hosted Windshift. Most values 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. |
SESSION_SECRET is accepted as a legacy fallback when SSO_SECRET is not set, but 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 |
- | Comma-separated accepted hostnames. Set this in production. |
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.
A plain-http BASE_URL only works for localhost by default. Any other http hostname or IP fails at startup with Failed to create CORS middleware ... insecure origin patterns; serve HTTPS instead, or set ALLOW_INSECURE_HTTP=true on a trusted LAN. See Docker for the 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. |
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. |
MAX_READ_CONNS |
30 |
Read connection pool size. On SQLite this caps concurrent readers; on PostgreSQL it also sizes the connection pool (max open = this value, max idle = half). Keep it well under your PostgreSQL max_connections. |
MAX_WRITE_CONNS |
1 |
SQLite write connection pool size. |
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=windshiftFiles
| 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. |
All server-side outbound HTTP blocks private and non-public addresses by default to reduce SSRF risk. Enable this switch when Windshift must reach internal endpoints such as a private identity provider, self-hosted SCM, or local LLM server:
ALLOW_LOCAL_CONNECTIONS=trueIt is a global switch, so only enable it when sensitive internal endpoints (cloud metadata services, admin panels) are not reachable from the Windshift host. The per-endpoint variables OIDC_ALLOWED_PRIVATE_CIDRS and LLM_ALLOWED_PRIVATE_CIDRS from earlier releases have been removed and are ignored.
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 (Ollama, LM Studio, internal gateways) require ALLOW_LOCAL_CONNECTIONS=true, see above.
Then use a Local / Custom AI connection with a base URL such as http://localhost:11434/v1, http://host.docker.internal:11434/v1, or http://172.17.0.1:11434/v1 depending on how Windshift reaches the model server.
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 two variables are the only CODING_AGENT_* settings the server reads. Agent
containers run on windshift-runner hosts, which are configured with WSRUNNER_*
variables in the runner process, not in the Windshift server process. The agent
image, Docker binary, worktree/cache location, and concurrency are all runner-side
settings. See Coding Agent Runner
for the runner compose file and the full WSRUNNER_* configuration table.
Notifications, Jira, and sidecars
| Variable | Default | Description |
|---|---|---|
VAPID_PUBLIC_KEY |
- | Web Push (VAPID) public key. Set together with VAPID_PRIVATE_KEY to enable push notifications. When unset, push is a no-op and the mobile app hides the enable-notifications option. |
VAPID_PRIVATE_KEY |
- | Web Push (VAPID) private key. Required alongside VAPID_PUBLIC_KEY. Generate a VAPID keypair once and keep it stable. |
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