Skip to main content
vibex-server is Vibex’s headless authoritative runtime. It uses the same DesktopRuntime core as the runtime embedded in the desktop, just in daemon form: the desktop adds a GPUI window, and the server adds daemon lifecycle. Both expose the exact same Remote v2 gateway, so a paired mobile client cannot tell which one it is connected to.
vibex-server is a single-user runtime: it has one Vibex home, one database, and one gateway. It is not a multi-tenant service. The host administrator is the user.

When to use it

  • You want sessions and Agents to live on a server and keep going when your laptop is closed.
  • You want to share the same sessions, workspaces, and credentials between your desktop and phone.
  • Your team has an always-on development machine that you want to reach from any device.
If you only need to forward traffic and do not need a hosted runtime, Relay is enough.

Quick start

The container image is multi-arch (linux/amd64, linux/arm64) and is updated with every release:
Image tag rules: rc follows the latest release candidate, latest points only to stable releases, and edge and sha-<commit> follow the default branch. The startup log prints server_id, endpoint, a one-time pairing_code (of the form NNN-NNN-NNN), pairing_link, tls_fingerprint, and a QR code. Hand these to a client to pair it; see Remote access and mobile. Regenerate a pairing code whenever you need a new one:

Commands

With no arguments it behaves like serve. --permission accepts read-only, approve-only, or full-control (the default is full-control).

Deployment shapes

Loopback only (default)

Binds to 127.0.0.1:8765 by default and publishes no ports. This suits bringing traffic in through an SSH tunnel or a reverse proxy.

Local network: self-signed certificate with pinning

When you have no domain or CA (a home or office LAN), the runtime provides a certificate it issues itself. Clients learn that certificate from the connection string and pin it—trust comes from the connection string, not from the network.
  • VIBEX_PUBLIC_HOST must be the address the client actually dials, including the port, and it must be a numeric local network address (192.168.x.x, 10.x.x.x, 172.16–31.x.x, or a link-local / unique-local IPv6 address).
  • The certificate stays the same for the lifetime of the runtime identity, so restarting the container does not require re-pairing. Only deleting /data invalidates it.
  • pinned_certificate really does terminate TLS at the gateway, so the listener is never plaintext. A client without the fingerprint cannot connect at all.

Public HTTPS

Public exposure requires VIBEX_DEPLOYMENT_MODE=public and one of the TLS strategies: Reverse proxy terminates TLS:
VIBEX_TRUST_FORWARDED_HEADERS can be enabled only in trusted_https_proxy mode; other modes reject forwarded headers. The gateway terminates TLS itself: set VIBEX_TLS_MODE=server_certificate and mount VIBEX_TLS_CERT_FILE / VIBEX_TLS_KEY_FILE (PEM) into the container.
The gateway validates the configuration combination at startup: a public listener without trusted TLS, a loopback entry in VIBEX_ALLOWED_HOSTS, or trusting forwarded headers outside trusted-proxy mode will all refuse to start. This is deliberate, so a misconfiguration cannot quietly degrade into an unauthenticated public service.

systemd (without Docker)

The repository ships a hardened unit file that runs as a host process, with the same environment variable contract:
The state directory defaults to /var/lib/vibex-server; see deploy/server/systemd.md in the repository.

Environment variables

The full list with defaults is in the environment variables reference. The most common ones:
Every entry in VIBEX_WORKSPACE_ROOTS must be an absolute path. If a mount point does not exist yet, it simply matches nothing rather than raising an error.

Credential storage

Provider API keys are stored on the server host. They never enter the database and are never returned to clients. The desktop writes keys into the operating system keychain. A headless server usually has no usable keychain (the default container seccomp profile rejects the keyutils syscalls the Linux keychain backend needs), so it writes provider-secrets.json in the runtime home instead, with owner-only permissions (0600). This is an explicit self-hosting tradeoff: the host administrator is the user.
The gateway does not log keys, pairing codes, or authentication tokens. Credential values are write-only once stored and are never returned to any client.

Security recommendations

  1. Keep the loopback default and publish through Tailscale Serve or a controlled reverse proxy.
  2. Public deployments must configure VIBEX_ALLOWED_HOSTS (exact hostnames, otherwise the gateway returns 421) and VIBEX_ALLOWED_ORIGINS (otherwise it returns 403). Native clients do not send an Origin header and are unaffected.
  3. Use vibex-server status to review paired devices regularly, and revoke to clean up promptly.
  4. List only the directories you truly need in VIBEX_WORKSPACE_ROOTS.
  5. The gateway exposes only the protocol and health check endpoints. It serves no browser UI and no business API.

Health check

/health and /api/info belong to Relay; the headless runtime’s info endpoint is /api/v2/info.