Skip to main content

Configuration Reference

There are two layers of configuration:

  1. Application config (vibed.yaml) — runtime settings for the vibed server. In Kubernetes this is rendered into a ConfigMap by the Helm chart and mounted at /etc/vibed/vibed.yaml.
  2. Helm values — cluster topology: namespaces, RuntimeClass, NetworkPolicy, the controller/router/caddy components, and the warm pools.

You normally set everything through Helm values; the chart renders the app config for you.

Config is loaded from a file, then VIBED_-prefixed environment variables override individual keys, then the result is validated. A missing config file is not an error — the server starts on defaults. Every field maps to a key defined in internal/config/config.go; the tables below are grouped by top-level section in that struct.

Application config (vibed.yaml)

organization:
name: "" # display name, e.g. "Acme Corp"

server:
transport: "stdio" # stdio | http | both
httpAddr: ":8080"
baseURL: "" # public URL for share-link generation
logFormat: "text" # text | json
logLevel: "info" # debug | info | warn | error
rateLimit: # covers /api, /mcp, and /v1 (incl. the deploy path)
enabled: false
requestsPerSecond: 10 # steady-state per client (reads)
burst: 20
writeRequestsPerSecond: 1 # stricter budget for deploy/create/update/delete
writeBurst: 5

auth:
enabled: false # enable before exposing the API
devInsecure: false # required to run auth-disabled on a non-loopback bind
mode: "apikey" # apikey | oauth | oidc
apiKeys: [] # see auth section below
# oidc: { issuer, audience, usernameClaim, roleClaim, adminRole, ... }
# tls: { enabled, certFile, keyFile, autoTLS }
# options: {} # extra keys read by out-of-tree auth providers

deployment:
preferredTarget: "auto" # auto | kubernetes
namespace: "default"
appsNamespace: "vibed-apps" # where /v1 creates VibedApps + warm pools live
readyTimeout: "10m" # how long a deploy waits for Ready before failing

storage:
backend: "local" # local | github | gitlab
local: { basePath: "/data/vibed/artifacts" }
tarball: # source-blob store for /v1/deploy
backend: "served" # served (DEV only) | s3 (PRODUCTION)
served:
basePath: "/data/vibed/sources"
publicBaseURL: "" # empty -> in-cluster Service DNS
s3:
endpoint: "" # empty for AWS; set for MinIO
bucket: ""
region: ""
presignTTL: "15m"

registry:
enabled: false
url: ""
insecure: false

store:
backend: "sqlite" # sqlite | memory | configmap
sqlite: { path: "/data/vibed.db" }
configmap: { name: "vibed-artifacts", namespace: "vibed-system" }
# options: {} # settings for out-of-tree store backends

kubernetes:
kubeconfig: "" # empty -> in-cluster / KUBECONFIG env
context: ""

limits:
maxTotalFileSize: 52428800 # 50 MiB
maxFileCount: 500
maxLogLines: 10000
maxConcurrentLogStreamsPerUser: 10 # <=0 -> safe default (not unlimited)
maxConcurrentLogStreamsGlobal: 100 # cap across all users; <=0 -> safe default

quotas:
enabled: false
maxAppsPerOwner: 0 # 0 = unlimited
maxAppsPerDepartment: 0 # 0 = unlimited
perDepartment: {} # override the department ceiling by name

audit:
failClosed: false # reject a mutating action if its audit write fails

gc:
enabled: true
interval: "1h"
maxAge: "24h"
dryRun: false

tracing:
enabled: false
endpoint: "" # OTLP gRPC endpoint; empty -> stdout
sampleRate: 1.0
served vs s3

served keeps the source tarball on vibeD's PVC and serves it over the in-cluster Service URL — dev only. Once a restrictive sandbox NetworkPolicy is in place (production), sandboxes have no cluster DNS or cluster-internal egress, so the agent can only pull from a pre-signed s3 URL. Use s3 (S3 or MinIO) in production.

organization

KeyTypeDefaultDescription
namestring""Organization display name, surfaced in the dashboard.

server

KeyTypeDefaultDescription
transportstringstdiostdio, http, or both. Validated — any other value fails startup.
httpAddrstring:8080Listen address for the HTTP transport (/v1 API, dashboard, streamable MCP).
baseURLstring""Public-facing base URL used to generate share links, e.g. http://localhost:8080.
logFormatstringtexttext or json.
logLevelstringinfodebug, info, warn, or error.
rateLimit.enabledboolfalseEnable per-client HTTP rate limiting. Covers /api, /mcp, and /v1 (including the deploy path). Off on a network transport logs a startup warning.
rateLimit.requestsPerSecondfloat10Steady-state rate per client for reads.
rateLimit.burstint20Max burst size per client for reads.
rateLimit.writeRequestsPerSecondfloat1Stricter steady-state rate for mutating verbs (deploy/create/update/delete), so one user can't flood the expensive deploy path. <=0 → safe default.
rateLimit.writeBurstint5Max burst for mutating verbs. <=0 → safe default.

auth

Governs authentication and TLS termination. When enabled is false the API is open (every request is treated as admin) — enable it before exposing vibeD. To guard against that being exposed by accident, vibeD refuses to start with auth disabled on a non-loopback bind unless devInsecure: true is set. See Authentication for a full walkthrough.

KeyTypeDefaultDescription
enabledboolfalseTurn authentication on.
devInsecureboolfalseAcknowledge running with auth disabled on a non-loopback bind. Required to start in that config (otherwise vibeD refuses); intended for local dev or a network-isolated in-cluster listener. The Helm chart's no-auth path sets it automatically.
modestring""apikey, oauth, or oidc. Out-of-tree providers may register additional modes.
apiKeyslist[]Configured API keys (see below). At least one is required when mode is apikey/oauth/empty.
oidcobjectOIDC settings (see below).
tlsobjectTLS termination (see below).
optionsmap[string]string{}Generic bag read by out-of-tree auth providers; core modes ignore it, so a new mode needs no schema change.

auth.apiKeys[]

KeyTypeDefaultDescription
keystringToken value, or env:VAR_NAME to read it from the environment.
namestringHuman-readable name; used as the caller's UserID.
scopeslist[]Allowed scopes; empty means all.
rolestringuseradmin or user.
departmentstring""Auto-assign the user to this department on first use.
storageobjectOptional per-user storage override (github or gitlab, see Storage).

auth.oidc

KeyTypeDefaultDescription
issuerstring""OIDC issuer URL. Required when mode is oidc.
audiencestring""Expected aud claim. Required when mode is oidc (blocks cross-app token reuse).
usernameClaimstringpreferred_usernameJWT claim for the username.
emailClaimstringemailJWT claim for the email.
roleClaimstringrealm_access.rolesJWT claim path for roles.
adminRolestringvibed-adminRole value that maps to a vibeD admin.
departmentClaimstring""JWT claim carrying the department name.
scopeslist["openid","profile"]Scopes to advertise.

auth.tls

KeyTypeDefaultDescription
enabledboolfalseTerminate TLS in vibed.
certFilestring""Path to the TLS certificate.
keyFilestring""Path to the TLS private key.
autoTLSboolfalseGenerate a self-signed cert for dev. When enabled, either certFile+keyFile or autoTLS is required.

deployment

KeyTypeDefaultDescription
preferredTargetstringautoauto or kubernetes.
namespacestringdefaultDefault working namespace for the control plane.
appsNamespacestringvibed-appsNamespace where /v1 creates VibedApp CRs. Must match where the warm pools live — agent-sandbox requires a SandboxClaim co-located with its SandboxTemplate.
readyTimeoutduration10mHow long deployers wait for a workload to become Ready before failing the deploy.

storage

The file-tree artifact store used by the legacy MCP build path. Distinct from storage.tarball, which is the source-blob store for the /v1/deploy path. See Storage.

KeyTypeDefaultDescription
backendstringlocallocal, github, or gitlab. Validated at startup.
localobjectbasePath (default /data/vibed/artifacts).
githubobjectowner, repo, branch (default main), tokenFile. owner and repo are required when backend is github.
gitlabobjecturl (default https://gitlab.com), projectID, branch (default main), token. projectID is required when backend is gitlab.
tarballobjectSource-blob store for /v1/deploy (see below).

Tokens in github.tokenFile / gitlab.token support env:VAR and file:PATH indirection.

storage.tarball

Selects how /v1/deploy persists the uploaded source tarball so vibed-agent can pull it.

KeyTypeDefaultDescription
backendstringservedserved (no extra infra) or s3.
servedobjectbasePath (default /data/vibed/sources; should be a PVC), publicBaseURL (in-cluster base the agent dials; the store appends /internal/sources/<id>.tar.gz).
s3objectendpoint (empty for AWS, set for MinIO), bucket, region, accessKey, secretKey, presignTTL (GET URL validity, default 15m).

registry

Optional OCI image registry used by paths that reference images.

KeyTypeDefaultDescription
enabledboolfalseEnable registry integration. When true, url is required.
urlstring""Registry base URL.
insecureboolfalseUse HTTP instead of HTTPS. See Registry.

store

The state store for control-plane objects (the control plane is stateless; all durable state lives here).

KeyTypeDefaultDescription
backendstringsqlitesqlite (default, recommended — scales per-row), memory, or configmap. Validated at startup.
sqliteobjectpath (default /data/vibed.db). Required when backend is sqlite.
configmapobjectname (default vibed-artifacts), namespace (default vibed-system). Small/dev deployments only — all artifacts share one ConfigMap, bounded by etcd's ~1MB object ceiling; use sqlite at scale.
optionsmap[string]string{}Passed verbatim to the backend factory. Core backends ignore it; an out-of-tree backend reads its own settings (DSN, pool size, …) from here, so adding a backend needs no schema change. See Store backends.

kubernetes

KeyTypeDefaultDescription
kubeconfigstring""Path to a kubeconfig. Empty uses in-cluster config; the KUBECONFIG env var fills this when set and the key is empty.
contextstring""Kubeconfig context to select.

limits

Guards on MCP tool inputs and log streaming.

KeyTypeDefaultDescription
maxTotalFileSizeint52428800Max total source size per deploy/update, in bytes (50 MiB).
maxFileCountint500Max number of files per deploy/update.
maxLogLinesint10000Max log lines returned per request.
maxConcurrentLogStreamsPerUserint10Max simultaneous /v1/logs SSE streams per authenticated user. <=0 falls back to a safe default (not unlimited).
maxConcurrentLogStreamsGlobalint100Max simultaneous /v1/logs SSE streams across all users, so many users can't collectively exhaust controller memory. <=0 → safe default.

quotas

Caps how many concurrent apps an owner or department may hold. Disabled by default; a new deploy is hard-gated when it would exceed either ceiling. Counts are over live VibedApps (by the vibed.dev/owner and vibed.dev/department labels); redeploys of an existing app do not count. See Quotas.

KeyTypeDefaultDescription
enabledboolfalseEnforce quotas.
maxAppsPerOwnerint0Per-user ceiling. 0 = unlimited.
maxAppsPerDepartmentint0Per-department aggregate ceiling. 0 = unlimited.
perDepartmentmap[string]int{}Override the department ceiling by department name.

audit

KeyTypeDefaultDescription
failClosedboolfalseWhen true, a mutating action (deploy/delete/rollback/suspend) whose audit write cannot be persisted is rejected — preferring availability loss over an untraceable change. The default fails open so dev clusters and the default install don't block deploys; production values flip this to true. See Audit log.

gc

The resource garbage collector, which reaps orphaned resources.

KeyTypeDefaultDescription
enabledbooltrueEnable garbage collection.
intervalduration1hGC cycle interval. Must be a valid Go duration when enabled.
maxAgeduration24hAge threshold for orphaned resources. Must be a valid duration.
dryRunboolfalseLog candidates without deleting.

tracing

OpenTelemetry distributed tracing.

KeyTypeDefaultDescription
enabledboolfalseEnable tracing.
endpointstring""OTLP gRPC endpoint (e.g. http://jaeger:4317). Empty exports to stdout.
sampleRatefloat1.0Sampling rate, 0.01.0.

Environment overrides

VIBED_-prefixed environment variables override the matching config key after the file is parsed, so you can inject secrets and per-environment settings without editing vibed.yaml. Only the keys below have overrides.

Environment variableOverrides
VIBED_ORGANIZATION_NAMEorganization.name
VIBED_SERVER_TRANSPORTserver.transport
VIBED_SERVER_HTTP_ADDRserver.httpAddr
VIBED_SERVER_BASE_URLserver.baseURL
VIBED_LOG_FORMATserver.logFormat
VIBED_LOG_LEVELserver.logLevel
VIBED_RATE_LIMIT_ENABLEDserver.rateLimit.enabled
VIBED_RATE_LIMIT_RPSserver.rateLimit.requestsPerSecond
VIBED_RATE_LIMIT_BURSTserver.rateLimit.burst
VIBED_AUTH_ENABLEDauth.enabled
VIBED_AUTH_MODEauth.mode
VIBED_AUTH_API_KEYappends a key and enables apikey auth
VIBED_AUTH_OIDC_ISSUERauth.oidc.issuer
VIBED_AUTH_OIDC_AUDIENCEauth.oidc.audience
VIBED_AUTH_OIDC_ADMIN_ROLEauth.oidc.adminRole
VIBED_TLS_ENABLEDauth.tls.enabled
VIBED_TLS_CERT_FILEauth.tls.certFile
VIBED_TLS_KEY_FILEauth.tls.keyFile
VIBED_TLS_AUTOauth.tls.autoTLS
VIBED_DEPLOYMENT_PREFERRED_TARGETdeployment.preferredTarget
VIBED_DEPLOYMENT_NAMESPACEdeployment.namespace
VIBED_STORAGE_BACKENDstorage.backend
VIBED_STORAGE_LOCAL_BASE_PATHstorage.local.basePath
VIBED_STORAGE_GITHUB_OWNERstorage.github.owner
VIBED_STORAGE_GITHUB_REPOstorage.github.repo
VIBED_REGISTRY_ENABLEDregistry.enabled
VIBED_REGISTRY_URLregistry.url
VIBED_STORE_BACKENDstore.backend
VIBED_STORE_SQLITE_PATHstore.sqlite.path
KUBECONFIGkubernetes.kubeconfig (only if unset)
VIBED_LIMITS_MAX_TOTAL_FILE_SIZElimits.maxTotalFileSize
VIBED_LIMITS_MAX_FILE_COUNTlimits.maxFileCount
VIBED_LIMITS_MAX_LOG_LINESlimits.maxLogLines
VIBED_GC_ENABLEDgc.enabled
VIBED_GC_INTERVALgc.interval
VIBED_GC_MAX_AGEgc.maxAge
VIBED_GC_DRY_RUNgc.dryRun
VIBED_TRACING_ENABLEDtracing.enabled
VIBED_TRACING_ENDPOINTtracing.endpoint
VIBED_TRACING_SAMPLE_RATEtracing.sampleRate
OTEL_EXPORTER_OTLP_ENDPOINTtracing.endpoint (and enables tracing)

KUBECONFIG selects the cluster when running outside it, and only applies when kubernetes.kubeconfig is empty.

Helm values (topology)

namespaces:
apps: vibed-apps # VibedApps + claims + templates + warm pools (one namespace)

runtime:
defaultClass: kata-qemu # kata-qemu (dev / no nested virt) | kata-fc (KVM)
installRuntimeClass: false # let Helm own the RuntimeClass
nodeSelector: {} # e.g. { vibed.dev/sandbox-node: "true" }
sandboxNetworkPolicy: Managed # Managed (agent-sandbox owns it) | Unmanaged (vibeD owns it)

networkPolicy:
enabled: false # vibeD-owned sandbox NetworkPolicy (prod: pair with Unmanaged)

controller:
domain: vibed.example.com # DNS suffix for app URLs
urlScheme: https # http in dev
urlPort: "" # optional port appended to app URLs; empty in dev (kind bridges host:80 → Caddy)

router: { enabled: true }
caddy:
enabled: true
tls:
dns01: { enabled: false, provider: cloudflare, tokenSecret: "" } # wildcard TLS in prod

workerd: { enabled: false, replicas: 3 } # fast-lane V8 isolates

warmPools: # one SandboxTemplate + SandboxWarmPool per template
node-24: { enabled: true, lane: general, image: "...", replicas: 50 }
python-313: { enabled: true, lane: general, image: "...", replicas: 50 }
go-123: { enabled: true, lane: general, image: "...", replicas: 20 }
base-al2023: { enabled: true, lane: general, image: "...", replicas: 30 }
static-nginx: { enabled: true, lane: fast, image: "...", replicas: 30 }

See deploy/helm/vibed/values.yaml for the fully-documented defaults and values-kind.yaml for the dev overlay. The controller takes flags (--vibed-domain, --app-url-scheme, --app-url-port, --pool-namespace) which the chart wires from the values above.

Extending the config

Several sections carry an options map (or an equivalent seam) so an out-of-tree Go module can plug in a provider without changing this schema:

  • auth.options / auth.mode — register a custom authentication mode. See Auth providers.
  • store.options / store.backend — register a custom state-store backend that reads its own DSN and tuning from options. See Store backends.

Feature availability is governed by an editions/feature-flag seam whose default enables all features; integrators building their own module can supply a different resolver. See Secrets and features.