Skip to content

Configuration Reference

Edit on GitHub

VibeXP is configured by a single required config.yaml. This page explains that model and summarizes the production-critical values — it does not duplicate every field (see Backend Configuration for the full list).

At startup the backend loads one YAML file, resolved in this order:

  1. the --config <path> flag,
  2. the VIBEXP_CONFIG_FILE environment variable,
  3. ./config.yaml in the working directory.

The file is required: a missing file fails fast with a message naming the expected path. String values support environment interpolation:

Syntax Meaning
${VAR} The value of env var VAR (empty, with a warning, if unset).
${VAR:-default} VAR when set and non-empty, otherwise default.
$${literal} A literal ${literal} (the $$ escapes interpolation).

Three files in the repo anchor the surface:

  • backend/config.example.yaml — the complete, commented field list, tuned for local development. Copy it to author your own config.yaml.
  • backend/config.schema.json — a JSON Schema for editor validation of the YAML.
  • backend/config.docker.yaml — the production-neutral default baked into the published image at /app/config.yaml (with VIBEXP_CONFIG_FILE pointed at it). Every operator knob in it is a ${VAR:-default} reference, so a container is configured with environment variables alone. To take full control, mount your own file over /app/config.yaml.

These are the values (shown as the env vars wired in the baked image config) you must review before exposing VibeXP to the internet. Defaults are for local evaluation only.

Env var config.yaml key Why it matters
ENCRYPTION_KEY security.encryption_key Required. Exactly 32 bytes (AES-256). Generate: openssl rand -base64 24 | cut -c1-32.
DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_NAME database.* PostgreSQL connection. Change DB_PASSWORD from the default; keep it in sync with Postgres POSTGRES_PASSWORD.
DB_SSLMODE database.sslmode disable (default) or require. Set require for managed Postgres that mandates TLS.
SESSION_ENCRYPTION_KEY auth.session_encryption_key 64 hex chars (32 bytes) backing the session cookie and OAuth state HMAC. Generate: openssl rand -hex 32.
FRONTEND_BASE_URL frontend.base_url Your real public URL, e.g. https://<your-app-host> — the single origin serving both SPA and API. A non-localhost value automatically disables the dev-login bypass.
OAUTH_AS_ISSUER_URL auth.oauth_as.issuer_url Public HTTPS URL enabling the embedded OAuth 2.1 Authorization Server (MCP tokens).
MCP_RESOURCE_URI mcp.resource_uri Public MCP URL, the required token audience (RFC 8707), e.g. https://<your-app-host>/mcp/v1/common.
INSTANCE_ADMIN_EMAILS auth.instance_admins Comma-separated emails of the root instance admins: they get the admin portal, finish first-run setup, and are the only ones who can grant the role to others (Instance Admin Portal). Set at least one before the first start. Since v0.15.0 an instance admin is also required to configure the instance’s outbound mail (Instance Email), so with this empty and no mail configured nobody can set it up.
AUTH_SETTINGS_RECOVERY_MODE auth.recovery_mode Leave unset. Set to true only to get back in after an authentication lockout: setup mode is forced on and every start logs a new one-time SETUP URL, while the configured providers keep working. Remove it once sign-in works again. See Lockout Recovery.
TRUSTED_PROXIES server.trusted_proxies Set if you run behind a reverse proxy or load balancer. Comma-separated CIDRs allowed to assert a client IP via X-Forwarded-For / X-Real-IP (e.g. 10.0.0.0/8,172.16.0.0/12; 192.168.1.5/32 for one host). Empty ignores those headers and uses the connecting peer, correct for a directly exposed instance. Left empty behind a proxy, per-IP rate limits collapse into one bucket and logs show the proxy address; the backend warns at startup. An invalid CIDR fails startup.
OUTBOUND_ALLOWED_CIDRS security.outbound_allowed_cidrs Comma-separated CIDRs the SSRF guard may dial even though they are loopback or private. Empty (the default) refuses every reserved range, which is what blocks a self-hosted embedding or model sidecar on a private Docker subnet. Declare only the network your own service runs on (e.g. 172.16.0.0/12, or 127.0.0.1/32 for a same-host Ollama). Link-local (169.254.0.0/16, fe80::/10, i.e. cloud metadata) and multicast (224.0.0.0/4, ff00::/8) can never be allowlisted; a malformed CIDR or one overlapping those ranges fails startup. Local development is exempt: a localhost FRONTEND_BASE_URL already permits reserved ranges.

The SPA is embedded in the backend and served same-origin, so there is no frontend deployment to configure. The backend serves runtime configuration at /config.js (as window.__VIBEXP_ENV__), rendered from the frontend.* config keys (VITE_MCP_ENDPOINT, GTM/GA4 analytics, …) — change one with an env var and a restart, no rebuild. Never put secrets there: /config.js is world-readable.

Company branding (name, logo, support and legal links) is not an env var. An instance admin sets it in the admin area under Settings → Site info: see Site Info (Branding).

The only frontend build-time values are deployment-neutral: the relative VITE_API_BASE_URL=/api/v1 and the VITE_RELEASE_SHA / VITE_RELEASE_DATE release stamps.

→ Full list: Frontend Configuration.

The backend has many more fields than the production-critical subset above (rate limits, retention, telemetry, …). They live in config.yaml; config.example.yaml documents every one.

Search ranking and AI summary defaults are no longer among them. Since v0.15.0 an instance admin sets them in the admin area, under Settings → Search and Settings → AI Summary (see Search & AI Summary Settings). The search: and ai_summary: sections are deprecated and only imported at startup (see Upgrading).

Instance email is no longer one of them. Since v0.15.0 an instance admin configures it in the admin area, under Settings → Email (see Instance Email). The email: section and its environment variables (EMAIL_PROVIDER, SMTP_*, …) are deprecated: they are imported at startup while nothing is stored and ignored once a provider is, as described in the upgrade note.

→ Full list: Backend Configuration.

  • Semantic search — embeddings run in-process; vector width is fixed at 1024. Embedding providers are configured per team in the app (model, chunk sizing, concurrency, and query/document prefixes included), not via environment.
  • Model providers: per-team OpenAI-compatible LLM endpoints, also managed in the app with encrypted API keys.
  • File attachments — enable the GCS emulator service and the related app variables. See Docker & Compose.
  • Scheduler: the in-process loop for recurring work; today it runs freshness-rule evaluation. On by default. Set SCHEDULER_ENABLED=false to turn it off (freshness evaluation stops with it), and tune it with SCHEDULER_TICK_INTERVAL / SCHEDULER_JOB_TIMEOUT / SCHEDULER_DUE_LIMIT. See Backend Configuration.

Every running instance serves its own API spec at /openapi.yaml and /openapi.json.