Skip to content
Wharfbase

Environment variables

Set these in /opt/wharfbase/.env (the installer’s file) or in your compose file. Settings changed in the UI win over the environment, except the ones marked as environment-only.

Variable Default Description
WB_ROLE all all (hub + local agent) · hub (UI/API only) · agent (no UI, connects to a hub)
WB_HOST 0.0.0.0 Listen address
WB_PORT 8480 Listen port
WB_PUBLIC_URL http://localhost:8480 External URL. https:// makes cookies Secure. Used in links/emails
WB_DATA_DIR /data Metadata DB, keys, tmp, exports, backups
WB_STORE_URL (_FILE) – (SQLite in WB_DATA_DIR) PostgreSQL 15+ for the metadata store instead (postgres://user:password@host:5432/db, ?sslmode=require for TLS; ADR 0001). The URL is never logged; wb doctor shows host, database and schema
WB_STORE_SCHEMA wharfbase The PostgreSQL schema for Wharfbase’s tables (created if missing)
WB_STORE_POOL 10 Connections each hub keeps to the PostgreSQL store
WB_SHARED_DIR WB_DATA_DIR Backups, export files and hub.key: a volume every standby hub mounts at the same path (docs/high-availability.md)
WB_LOG_LEVEL info trace|debug|info|warn|error
WB_LOG_FORMAT json json|pretty
WB_TRUST_PROXY false true, or a comma list of CIDRs, for X-Forwarded-*
WB_COOKIE_SECURE auto auto (Secure when WB_PUBLIC_URL is https or WB_TLS_* is set) · true · false
WB_TLS_CERT_FILE / WB_TLS_KEY_FILE – Serve HTTPS directly on WB_PORT (TLS 1.2+), with PEM files: the certificate (with its chain) and its key. Both or neither; a missing file or a key that doesn’t match stops the start (CONFIG_INVALID). Renewed files are picked up within 10 minutes, without a restart. A reverse proxy is still the easier way to get and renew certificates
WB_MASTER_KEY (_FILE) generated → /data/master.key 32 bytes, base64. Encrypts the vault
WB_SETUP_TOKEN random Force a known setup token (automation)
WB_SESSION_TTL_HOURS 12 Absolute web session lifetime
WB_SESSION_IDLE_MINUTES 60 Idle timeout
WB_CLI_SESSION_TTL_DAYS 30 CLI session lifetime
WB_MIN_FREE_MB 64 Below this much free space in the data volume, changes are refused with STORAGE_FULL; reads, sign-in and deletes keep working. 0 turns the check off
WB_REQUIRE_TOTP_FOR_ADMINS false Initial value of security.requireTotpForAdmins: admins and the owner must set up two-factor authentication before anything else (MFA_SETUP_REQUIRED)
WB_UPDATE_CHECK true Initial value of updates.check: once a day, GET {WB_LICENSE_SERVER}/v1/releases/latest, with nothing about the instance (no version, no ID; the comparison happens locally). Admins see a newer release in the sidebar, Settings → General and wb doctor. Builds without a release version (0.0.0, from source) don’t check
WB_TELEMETRY false Initial value of telemetry.enabled (also asked at setup): once a day, an anonymous report to {WB_LICENSE_SERVER}/v1/telemetry, exactly TelemetryReportSchema (packages/licensing/src/telemetry.ts): a random ID that isn’t the instance ID, the version, plan and role, counts of servers, users and databases, databases per engine, and the activation funnel. Settings → General shows the next report
Variable Default Description
WB_DOCKER true false: no Docker here, as in a Kubernetes pod: no Docker discovery, networks, relays, shells or Docker-run backups; /readyz doesn’t wait for Docker; setup shows Docker as off
WB_DOCKER_HOST DOCKER_HOST, else unix:///var/run/docker.sock (compose sets tcp://socket-guard:2375) Docker API endpoint
WB_DOCKER_API_VERSION auto Pin the API version (e.g. 1.45)
WB_SELF_CONTAINER auto Override self-detection (name or id)
WB_SCAN_ON_BOOT true Full scan at startup
WB_SCAN_EVENT_DEBOUNCE_MS 1500 Debounce for Docker events → incremental scan
WB_SCAN_CONCURRENCY 8 Parallel inspects/probes
WB_PROBE_TIMEOUT_MS 1500 TCP connect timeout per probe
WB_DF_CACHE_MINUTES 10 Cache for /system/df volume sizes
WB_NETWORK_ATTACH auto auto|ask|off|relay. relay: Wharfbase joins only wharfbase_relay, and a relay container per database forwards its port (needs GUARD_ALLOW_RELAY)
WB_NETWORK_DETACH_UNUSED true Auto-detach networks no activated DB has needed for 30 min
WB_SQLITE_SCAN true Scan container volumes for database files: SQLite, DuckDB and Parquet
WB_SQLITE_SCAN_MAX_BYTES_PER_CONTAINER 268435456 Tar bytes budget per container (256 MB)
WB_SQLITE_SNIFF_ALL false Check the magic of every file (not just .db/.sqlite…/.duckdb/.ddb/.parquet names)
WB_SQLITE_MAGIC_ANY_MAX 1073741824 Max file size for name-agnostic sniffing
WB_HOST_SCAN false Enable the host scan (needs the host-scan compose override)
WB_HOST_ROOT /host Where the host root is mounted
WB_SQLITE_SCAN_PATHS /host/srv,/host/opt,/host/home,/host/var/lib Host walk roots for SQLite, DuckDB and Parquet files
WB_SQLITE_SCAN_MAX_DEPTH 6 Host walk depth
WB_FINDINGS_ACTIVE_CHECKS true Allow harmless unauthenticated checks (e.g. Mongo listDatabases)
WB_SECRET_HINTS on-demand off (never read secret env values) · on-demand (explicit per-use action, audited)

Kubernetes discovery reads pods, Services, StatefulSets, Deployments, PersistentVolumeClaims, NetworkPolicies and Namespaces through the API, read-only (docs/kubernetes.md):

Variable Default Description
WB_KUBERNETES auto auto: on in a pod (KUBERNETES_SERVICE_HOST set) or with WB_KUBERNETES_API · true (logs why when it can’t) · false
WB_KUBERNETES_API in a pod, https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT The API server, to read a cluster from outside it
WB_KUBERNETES_TOKEN – Bearer token (with WB_KUBERNETES_API)
WB_KUBERNETES_TOKEN_FILE in a pod, the service account’s token Read again every minute: projected tokens rotate. Not both this and WB_KUBERNETES_TOKEN
WB_KUBERNETES_CA_FILE in a pod, the service account’s ca.crt PEM bundle for the API server; else the system’s CAs
WB_KUBERNETES_NAMESPACES – Comma list; empty for every namespace (needs cluster-wide list rights)
WB_KUBERNETES_POD_NAME, WB_KUBERNETES_POD_NAMESPACE HOSTNAME, the service account’s namespace Wharfbase’s own pod (the manifests set them from the downward API): skipped by discovery, and the source side of NetworkPolicy checks
Variable Default Description
WB_STATEMENT_TIMEOUT_MS 30000 Per statement
WB_MAX_RESULT_ROWS 10000 Hard cap for SQL editor results
WB_MAX_RESULT_BYTES 52428800 Hard cap for streamed result size (50 MB)
WB_POOL_MAX_PER_DB 3 Connections per (connection, database) pool
WB_POOL_IDLE_MS 300000 Idle pool eviction
WB_MAX_SESSIONS 50 Global open driver sessions
WB_PRODUCTION_READ_ONLY true Production-tagged DBs open read-only by default
WB_AUDIT_SQL_TEXT true Store the first 200 chars of executed SQL in the audit log
WB_AUDIT_ROW_VALUES false Store changed values in the audit log
WB_WRITE_APPROVALS false Team: editors’ writes to production databases wait for an admin’s approval (the data.writeApprovals setting’s default)
Variable Default Description
WB_LICENSE_KEY (_FILE) – License token (alternative to pasting it in the UI): activated in the background at boot when it differs from the stored one
WB_LICENSE_SERVER https://license.fleeq.net License API
WB_HUB_URL – Agent role: hub base URL
WB_AGENT_TOKEN (_FILE) – Agent role: one-time enrollment token
WB_AGENT_NAME hostname Agent display name
WB_AGENT_ALLOW_INSECURE_HUB false Agent role: allow an http:// hub on a public address. Private addresses (RFC 1918, CGNAT, link-local, .local/.internal/.lan/.home.arpa, single-label names) are allowed with a warning
WB_SMTP_URL (_FILE) – smtp(s)://user:pass@host:port for alerts/invites (Pro)
WB_SMTP_FROM – From address
WB_OIDC_ISSUER, WB_OIDC_CLIENT_ID, WB_OIDC_CLIENT_SECRET (_FILE) – SSO (Team). Used until SSO is saved under Settings → Single sign-on, which then wins
WB_OIDC_ALLOWED_DOMAINS – Comma list: domains new SSO accounts may come from (empty: any)
WB_OIDC_DEFAULT_ROLE viewer Role for new SSO users (viewer, editor, admin)
Variable Default Description
GUARD_LISTEN 0.0.0.0:2375 Listen address (only on the internal network)
GUARD_DOCKER_SOCKET /var/run/docker.sock Upstream socket
GUARD_ALLOW_NETWORK_ATTACH true Allow network connect/disconnect for the self container only
GUARD_ALLOW_ARCHIVE true Allow GET /containers/{id}/archive (SQLite snapshots/scan)
GUARD_ALLOW_EPHEMERAL false Allow creating ephemeral job containers (backups, wb shell)
GUARD_ALLOW_RELAY false Allow relays: creating wharfbase_relay, joining it with attach off, and relay containers that pass the checks in socket-guard.md
GUARD_EPHEMERAL_IMAGES see plan P3.1 Regex allowlist of images for ephemeral containers; always matched against the whole image reference (anchored for you)
GUARD_SELF_LABEL wharfbase.self=true How the guard identifies the Wharfbase container
GUARD_LOG_LEVEL info

Read by compose and the installer from <install dir>/.env. They’re passed through to the server, which reads only WB_REGISTRY.

Variable Default Description
WB_VERSION latest Image tag: latest, next, a major (1), minor (1.2) or exact version
WB_REGISTRY docker.io/wharfbase Image prefix. The hub also writes it into the agent compose files it hands out, as their default. A release built with another IMAGE_PREFIX (§K.5) defaults to that
WB_BIND 0.0.0.0 Host address the web port is published on
WB_PORT 8480 Host port (inside the container the server always listens on 8480)
WB_DOCKER_SOCKET /var/run/docker.sock Docker socket the guard mounts (the installer sets it for rootless Docker)
WB_GUARD_ALLOW_NETWORK_ATTACH true Passed to the guard’s GUARD_ALLOW_NETWORK_ATTACH
WB_GUARD_ALLOW_EPHEMERAL false Passed to the guard’s GUARD_ALLOW_EPHEMERAL
WB_GUARD_ALLOW_RELAY false Passed to the guard’s GUARD_ALLOW_RELAY
COMPOSE_FILE docker-compose.yml Compose files in use; the installer puts docker-compose.host-scan.yml second with --host-scan and keeps any files you add after it
WB_INSTALL_BASE_URL https://fleeq.net/wharfbase/get (installer environment) where compose files, SHA256SUMS and install.sh are downloaded from