Skip to content

Configuration Reference

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:

SyntaxMeaning
${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 varconfig.yaml keyWhy it matters
ENCRYPTION_KEYsecurity.encryption_keyRequired. Exactly 32 bytes (AES-256). Generate: openssl rand -base64 24 | cut -c1-32.
DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_NAMEdatabase.*PostgreSQL connection. Change DB_PASSWORD from the default; keep it in sync with Postgres POSTGRES_PASSWORD.
DB_SSLMODEdatabase.sslmodedisable (default) or require. Set require for managed Postgres that mandates TLS.
SESSION_ENCRYPTION_KEYauth.session_encryption_key64 hex chars (32 bytes) backing the session cookie and OAuth state HMAC. Generate: openssl rand -hex 32.
FRONTEND_BASE_URLfrontend.base_urlYour 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.
AUTH_PROVIDERauth.providerOne of google, github, oidc. Several at once needs a mounted config.yaml with auth.providers: [...].
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET (or GITHUB_*, OIDC_*)auth.<provider>.*Credentials for the chosen provider (plus *_REDIRECT_URI if it differs from <FRONTEND_BASE_URL>/api/v1/auth/callback, and OIDC_ISSUER_URL for OIDC).
OAUTH_AS_ISSUER_URLauth.oauth_as.issuer_urlPublic HTTPS URL enabling the embedded OAuth 2.1 Authorization Server (MCP tokens).
MCP_RESOURCE_URImcp.resource_uriPublic MCP URL, the required token audience (RFC 8707), e.g. https://<your-app-host>/mcp/v1/common.
INSTANCE_ADMIN_EMAILSauth.instance_adminsComma-separated emails granted the /api/v1/admin portal. Empty leaves the feature dormant.
AUTH_ALLOWED_DOMAINS / AUTH_ALLOWED_EMAILSauth.access_allowlist.*Optional. Restrict sign-in by email domain and/or exact address (comma-separated). A user is allowed if either matches; both empty means open.
TRUSTED_PROXIESserver.trusted_proxiesSet 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_CIDRSsecurity.outbound_allowed_cidrsComma-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_SITE_NAME, VITE_SITE_URL, VITE_SUPPORT_EMAIL, VITE_MCP_ENDPOINT, GTM/GA4 analytics, …) — rebrand with an env var and a restart, no rebuild. Never put secrets there: /config.js is world-readable.

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, search ranking, email, telemetry, …). They live in config.yaml; config.example.yaml documents every one.

→ 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. On by default, but no job types ship yet, and it has no env var in the baked image config, so tuning scheduler.* means mounting your own config.yaml. See Backend Configuration.

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