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. |
SESSION_IP_BINDING |
log |
Handle a client-IP change on an existing session. Use log, strict, or off. Invalid values stop startup. |
WEBAUTHN_RP_ID |
BASE_URL host |
WebAuthn relying-party ID. Use a hostname, or a full HTTP or HTTPS URL from which Windshift extracts the hostname. Falls back to the process host name, which is the container ID in Docker. See WebAuthn relying-party ID in containers. |
WEBAUTHN_RP_NAME |
Windshift |
Display name shown by authenticators. |
The default SESSION_IP_BINDING=log records an IP change and keeps the session active. Use strict to reject a changed IP, or off to skip the comparison. Test strict with your proxy, mobile clients, and changing networks before you enforce it.
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. |
Outbound TLS
| Variable | Default | Description |
|---|---|---|
TLS_SKIP_VERIFY |
false |
Disable certificate-chain and hostname verification for outbound HTTPS, SMTP, IMAP, and LDAP connections. |
Keep this setting false in production. Set it to true only when every affected destination is trusted and uses a certificate that Windshift cannot verify. The setting applies to the whole process.
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 |
true |
Allow server-side HTTP clients (SCM, Jira, LLM, OIDC, webhooks, SMTP) to reach local, loopback, and private-network addresses. |
By default, Windshift allows server-side outbound HTTP to local, loopback, and private-network addresses. To restore private-address blocking, set the variable to false:
ALLOW_LOCAL_CONNECTIONS=falseThe equivalent CLI setting is:
./windshift --allow-local-connections=falseThis is a global switch. When set to false, integrations cannot reach private endpoints such as a self-hosted SCM, Jira Data Center, private identity provider, local LLM server, internal webhook target, or internal SMTP server. Use network policy to keep sensitive endpoints, such as cloud metadata services and admin panels, out of reach of the Windshift host. Windshift ignores the removed OIDC_ALLOWED_PRIVATE_CIDRS and LLM_ALLOWED_PRIVATE_CIDRS variables.
See Production-ready self-hosting for normal and hardened deployment profiles.
Process memory and cache budget
| Variable | Default | Description |
|---|---|---|
WINDSHIFT_MEMORY_LIMIT_MB |
2048 MiB |
Total Windshift process-memory budget. Values below 512 MiB fail at startup. |
The value uses MiB. It overrides --memory-limit-mb when both are set. Windshift gives the Go runtime an 80% soft heap target and gives BigCache 25% of the process budget, capped at 512 MiB. This is not a hard RSS limit. Set the container memory limit to at least the declared process budget.
Administrators can inspect the resolved budget, cache capacity, entries, hits, misses, and evictions under Admin → Diagnostics → Cache memory.
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, work by default. Set ALLOW_LOCAL_CONNECTIONS=false to block them.
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
SESSION_IP_BINDING=log
# 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: block egress to private/loopback endpoints (local LLM, internal IdP/SCM)
# ALLOW_LOCAL_CONNECTIONS=false
# Keep certificate verification enabled. Do not set true for normal production use.
TLS_SKIP_VERIFY=falseUsing 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
# Blocks private/loopback egress for all server-side HTTP clients when set to false.
ALLOW_LOCAL_CONNECTIONS=Validate
varlock loadRun with validation
varlock run -- docker compose up -d