Skip to main content

Authentication & HTTPS

vibeD protects its MCP and API endpoints with bearer token authentication, using the official MCP SDK auth middleware. This ensures MCP clients like Claude Desktop, Cursor, and others can securely connect to your vibeD instance.

Why Authenticate?

MCP clients do not trust unsecured tool servers. Without authentication:

  • Any process on the network could invoke deployment tools
  • Built artifacts and source code could be exposed
  • There is no audit trail of who deployed what

With auth disabled, every request is treated as admin. To stop that being exposed by accident, vibeD refuses to start when auth is disabled and the server binds a non-loopback address, unless you explicitly acknowledge it with auth.devInsecure: true. Use that only for local dev or a network-isolated in-cluster listener; the Helm chart's no-auth path sets it for you. The right move for anything reachable by others is to enable auth.

Quick Start

The fastest way to enable auth is via a single environment variable:

export VIBED_AUTH_API_KEY="vibed_sk_your_secret_key_here"
./vibed --config vibed.yaml --transport http

This automatically enables API key authentication. MCP clients then connect with:

Authorization: Bearer vibed_sk_your_secret_key_here

Authentication Modes

API Key Mode (Default)

Simple bearer tokens validated against a configured list. Best for single-user setups, CI/CD pipelines, and development.

auth:
enabled: true
mode: "apikey"
apiKeys:
- key: "env:VIBED_API_KEY" # Resolved from environment variable
name: "default"
- key: "vibed_sk_ci_deploy_key" # Literal value
name: "ci-pipeline"
scopes: ["deploy"]

Key features:

  • Keys can be literal values or resolved from environment variables using the env: prefix
  • Keys also support file:/path/to/token to read tokens from files
  • Each key has a human-readable name; the owning user identity (UserID) is apikey-<name>, and a user record is auto-provisioned under that ID on first authentication
  • Optional scopes restrict what the key can do (empty = unrestricted)
  • Constant-time comparison prevents timing attacks
  • Suspension is enforced: setting a key's user record status: suspended immediately revokes access on the next request (401)
Upgrading to v0.4.4

The canonical user ID for a static API key is now apikey-<name> everywhere — request identity, the provisioned user record, the role map, and artifact ownership. Before v0.4.4 the raw name was used for ownership, so artifacts deployed by a static-key user on an older version are owned under the bare name and won't match after upgrade. If you rely on static-key owner-scoping with pre-existing artifacts, re-key their ownership or redeploy. OIDC and no-auth users are unaffected.

OIDC Mode

For production environments with an OpenID Connect identity provider (Keycloak, Auth0, Okta, Google). vibeD validates JWT tokens directly against the provider's JWKS endpoint.

auth:
enabled: true
mode: "oidc"
oidc:
issuer: "https://auth.example.com/realms/vibed" # OIDC issuer URL
audience: "vibed" # Expected audience claim
usernameClaim: "preferred_username" # JWT claim for username
emailClaim: "email" # JWT claim for email
roleClaim: "realm_access.roles" # JWT claim for roles
adminRole: "vibed-admin" # Role value that grants admin access
scopes: # Scopes to request
- "openid"
- "profile"
- "email"

vibeD publishes an OAuth Protected Resource Metadata endpoint at /.well-known/oauth-protected-resource so MCP clients can discover the authorization server automatically.

Environment variable overrides:

VariableDescription
VIBED_AUTH_OIDC_ISSUEROIDC issuer URL
VIBED_AUTH_OIDC_AUDIENCEExpected audience claim
VIBED_AUTH_OIDC_ADMIN_ROLERole that grants admin access

OAuth Proxy Mode

For environments where an external OAuth gateway or reverse proxy validates tokens. vibeD trusts the proxy to authenticate requests.

auth:
enabled: true
mode: "oauth"

The external proxy (e.g., OAuth2 Proxy, Pomerium, or an API gateway) should:

  1. Validate the OAuth token against your identity provider
  2. Forward the request to vibeD with the original Authorization: Bearer header
  3. Set the X-Forwarded-User header with the authenticated user's identity

Custom Modes (Extensible Registry)

Auth modes are a registry, not a fixed enum. The core registers apikey, oauth, and oidc from init(), and an out-of-tree Go module can register additional modes (for example a SAML SP or a bespoke JWT issuer) the same way — without patching the core. Set auth.mode to the registered name and vibeD resolves the provider at startup:

auth:
enabled: true
mode: "saml" # any registered mode; unknown modes fail fast at startup

An unknown auth.mode is rejected at startup with an error listing the registered modes, so a typo can never silently disable auth.

Each mode is a provider that contributes a required token Verifier — checked on every authenticated request — and, optionally, a set of public login routes. The built-in bearer-only modes (apikey, oauth, oidc) contribute no routes. A mode whose login flow needs browser-facing endpoints (for example an SSO metadata document or an assertion-consumer / callback endpoint) declares them as routes, and vibeD mounts those routes outside the bearer-auth middleware. That is deliberate: a login route is how a caller obtains a session in the first place, so it cannot itself require one. Login routes must live on public paths — not under /api, /v1, /mcp, or /internal/sources/.

See Custom Auth Providers for the extension surface, the exported types in pkg/plugin, and how to build a custom binary.

What Gets Protected

EndpointAuthentication
/mcp/*Required when auth is enabled
/api/*Required when auth is enabled
/api/share/*Always open (public share links)
/healthzAlways open (Kubernetes liveness probe)
/readyzAlways open (Kubernetes readiness probe)
/metricsAlways open (Prometheus scraping)
/ (dashboard)Always open (static frontend assets)

HTTPS / TLS

Since bearer tokens are sent on every request, running without TLS exposes credentials on the network. vibeD supports three TLS configurations:

Certificate Files (Production)

Use certificates from cert-manager, Let's Encrypt, or your PKI:

auth:
tls:
enabled: true
certFile: "/etc/vibed/tls/tls.crt"
keyFile: "/etc/vibed/tls/tls.key"

Or via environment variables:

export VIBED_TLS_ENABLED=true
export VIBED_TLS_CERT_FILE=/etc/vibed/tls/tls.crt
export VIBED_TLS_KEY_FILE=/etc/vibed/tls/tls.key

Auto-Generated Self-Signed Certificate (Development)

For local development and testing, vibeD can generate a self-signed certificate automatically:

auth:
tls:
enabled: true
autoTLS: true

Or:

export VIBED_TLS_ENABLED=true
export VIBED_TLS_AUTO=true

The self-signed certificate covers localhost, 127.0.0.1, ::1, and the system hostname. MCP clients will need to trust this certificate or skip verification.

warning

Do not use autoTLS in production. Use proper certificates from a trusted CA.

TLS Termination at Ingress (Kubernetes)

In Kubernetes, TLS is typically terminated at the Ingress controller. In this case, disable TLS in vibeD and configure your Ingress:

# vibed.yaml — no TLS needed, Ingress handles it
auth:
enabled: true
mode: "apikey"
# tls not enabled — Ingress terminates TLS
# Kubernetes Ingress with cert-manager
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vibed
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- vibed.example.com
secretName: vibed-tls
rules:
- host: vibed.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vibed
port:
number: 8080

Helm Chart Setup

Enable Auth with a Secret

Create a Kubernetes Secret with your API key:

kubectl create secret generic vibed-auth \
--from-literal=api-key="vibed_sk_your_secret_key_here"

Then enable auth in your Helm values:

auth:
enabled: true
mode: "apikey"
existingSecret: "vibed-auth" # References the Secret above

Enable TLS with cert-manager

Create a Certificate resource:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: vibed-tls
spec:
secretName: vibed-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- vibed.example.com

Then enable TLS in your Helm values:

auth:
enabled: true
mode: "apikey"
tls:
enabled: true
existingSecret: "vibed-tls" # References the cert-manager Secret

Artifact Ownership

When authentication is enabled, vibeD enforces per-user artifact isolation:

  • Deploy stamps each artifact with the deploying user's owner_id (the API key's name field)
  • List only returns artifacts owned by the current user
  • Status, Update, Delete, and Logs verify ownership before proceeding
  • Accessing another user's artifact returns "not found" (not "forbidden") to avoid leaking artifact existence

When authentication is disabled, ownership checks are skipped and all users see all artifacts.

Connecting MCP Clients

Claude Desktop

Add vibeD as a remote MCP server in Claude Desktop settings:

{
"mcpServers": {
"vibed": {
"url": "https://vibed.example.com/mcp/",
"headers": {
"Authorization": "Bearer vibed_sk_your_secret_key_here"
}
}
}
}

Environment Variables Reference

VariableDescriptionExample
VIBED_AUTH_API_KEYSet a single API key (auto-enables auth)vibed_sk_...
VIBED_AUTH_ENABLEDEnable/disable authenticationtrue
VIBED_AUTH_MODEAuthentication modeapikey, oidc, or oauth
VIBED_AUTH_OIDC_ISSUEROIDC issuer URLhttps://auth.example.com
VIBED_AUTH_OIDC_AUDIENCEOIDC expected audiencevibed
VIBED_AUTH_OIDC_ADMIN_ROLEOIDC role granting adminvibed-admin
VIBED_TLS_ENABLEDEnable HTTPStrue
VIBED_TLS_CERT_FILEPath to TLS certificate/etc/tls/tls.crt
VIBED_TLS_KEY_FILEPath to TLS private key/etc/tls/tls.key
VIBED_TLS_AUTOGenerate self-signed certtrue