What is a headless runtime? Think of it as Vibex without a window. It owns Agent sessions, workspaces, Git, terminals, and provider profiles, and behaves exactly like the desktop app — it just runs on a server, and you operate it through a desktop or mobile client. Its program name is
vibex-server.1. Cloud development: run Vibex on a server
Agents read and write code on the server and run commands there, so prepare the server first and connect clients afterwards.Before you start
- A Linux server with Docker. For a single user, 1 vCPU and 2 GB of RAM is enough to start; running several Agents benefits from 2 vCPU and 4 GB or more.
- Your code must be reachable on the server: either clone it there, or mount a host directory into the container (the example below mounts one).
- Agent accounts and API keys are configured later, from the desktop client: add them under Config Center (see Config Center). Never put them in the compose file or commit them.
Step 1: start the runtime
The project repository already contains a completedocker-compose.yml deployment file — open it directly: deploy/server/docker-compose.yml. The version below is a minimal example trimmed for this walkthrough; save it as docker-compose.yml in any directory on the server:
Use
rc to follow the newest release candidate or latest for the newest stable release; pin a specific version only if you need to. If you already cloned the repository, you can also build from source with its deployment files: docker compose -f deploy/server/docker-compose.yml up --build -d vibex-server.pairing_code=123-456-789— a one-time code that expires after five minutes by default.pairing_link=vibex://pair#/code/...— a connection string that already carries the server address, the one-time code, and the server certificate (DER). Copy the whole string; the client pins that certificate before its first request, so a server with a self-signed certificate needs no system CA.
If the server is on the public internet
A public deployment adds exactly one requirement: HTTPS. Let Caddy obtain the certificate while the runtime only listens on loopback:Caddyfile next to it:
80, 443, and SSH. Keep 8765 on loopback and out of the public internet. After you replace the domain and address with your own, VIBEX_ALLOWED_HOSTS and VIBEX_ALLOWED_ORIGINS must match the domain clients actually use, or requests are rejected.
Step 2: connect the desktop
- Select the Runtime button in the title bar to open the runtime manager.
- Select Add runtime…, choose the Connection string tab, paste the whole
vibex://pair#/code/...value, and select Pair. This also works when the server uses a self-signed certificate, because the fingerprint travels inside the string. - Alternatively, choose the Pairing code tab and enter the Server address and One-time pairing code.
- After pairing, the runtime’s Certificate row shows a
sha256:fingerprint. Compare it withtls_fingerprintin the server log. - Select Switch to this runtime to make it current. From now on, sessions, files, Git, and terminals in the desktop come from the server. To go back to your own machine, select This device in the list and switch to it. To remove the runtime, select Remove in its details — that deletes only the local device credential; the server-side authorization stays until it is revoked on the server.
Step 3: connect the mobile client
- Open the mobile app and choose Pair with a Cloud Server.
- Enter the server address (for example
192.168.1.10:8765) and the pairing code, then select Pair with Code. - When the server uses a self-signed certificate, paste the
vibex://pair#/code/...string into the connection string field instead; it carries the certificate too. - Confirm the pairing; what this device may do comes from the server when it mints the pairing code, and defaults to Full control. To grant less, mint a new code on the server with
docker exec vibex-server vibex-server pairing-code --permission read-only(choices:read-only,approve-only,full-control).
Step 4: let Agents see your code
Agents run on the server, so they only see directories inside the server (container). Your code therefore has to live there:- Clone it on the server into
/data/repos/your-project, or - Mount a host directory into the container (the
- /srv/repos:/data/reposline above).
VIBEX_WORKSPACE_ROOTS (the /data:/data/repos value above). In any client, open a new session, select the project directory picker, choose Choose another directory, and pick your project under /data or /data/repos.
Mounting a directory without listing it in
VIBEX_WORKSPACE_ROOTS leaves it unbrowsable for clients; listing a path without mounting it leaves the directory nonexistent inside the runtime.Step 5: day-two operations
2. Remote development: your phone reaching your desktop
Your computer stays the authority: Agents, files, Git, and terminals all run on the desktop, and the phone only gets a window to view and operate them. Use this when you are away and want to check progress, answer a question, or approve a request.Before you start
- The desktop app is running and the computer stays awake; sleep drops the connection.
- The phone and the computer can reach each other: the same Wi-Fi is easiest, and Tailnet or a self-hosted Relay cover the rest.
Step 1: publish remote access from the desktop
- Select the pair mobile device icon in the top toolbar. The dialog has two tabs: Pair publishes a new pairing, and Paired devices (N) manages the devices that already hold a grant.
- Choose how the phone will connect:
- Tailnet (recommended) — private access through Tailscale or another private network; good when you are not on the same Wi-Fi.
- Direct HTTPS — you have your own HTTPS address that points at this computer.
- Self-hosted Relay — the phone and computer cannot reach each other directly, so your own Relay forwards encrypted traffic.
- Fill in the address the dialog asks for (Direct expects
https://your-address, Relay expectshttps://your-relay), choose what this phone may do (the default is Read only; see Permission levels), and select Publish. - A QR code and a pairing link appear: scan to pair, or select Copy link and send it to the phone. The link expires quickly; select Regenerate when it does.
Step 2: pair the phone
- On the same Wi-Fi: the mobile app discovers nearby desktops; select yours and confirm.
- On another network: scan the QR code or open the copied
vibex://link. - Manually: choose Pair with Code in the mobile app and enter the address and pairing code shown on the desktop.
Step 3: what the phone can do
Mobile has no Config Center, so it cannot manage Agents, providers, MCP, or Skills. Its Settings contain only Connection, Session timeline, Appearance, Notifications, and About.
Every write is ultimately produced by the authoritative runtime; mobile shows its projection.
When direct access fails: self-hosted Relay
Phones and computers are often behind corporate networks or carrier NAT, so they cannot reach each other. Run the Relay on a server both sides can reach; it only forwards encrypted frames and cannot read them:127.0.0.1:9700), then publish remote access on the desktop with Self-hosted Relay and enter https://your-relay-domain.
The Relay is pure forwarding: it does not store sessions, files, or provider profiles, and it does not decrypt content. Rooms and connections live in memory, so a restart clears them and devices rebuild them on reconnect.
Disconnects and reconnects
After a network change, screen lock, or app resume, clients re-authenticate and catch up on missing history: they show authoritative session and timeline state first, then resume live updates.Permission levels
Choose a permission when you pair a mobile device, and grant the smallest one that works. The level is decided by the initiating side when it creates the pairing, and a client cannot raise it on its own:
Revoke devices on the authoritative side:
- When the desktop is the authority, open Pair mobile, switch to the Paired devices (N) tab, and select Revoke on the device, then confirm. Each row shows the device’s status, permission, and last activity, and Refresh devices reloads the list; more than six devices are paged.
- When a headless runtime is the authority, run
docker exec vibex-server vibex-server revoke DEVICE_ID(orvibex-server revoke DEVICE_IDon the server).
Security checklist
- Keep the runtime’s
8765port on loopback or your private network, and always use HTTPS on the public internet. The authority listens on loopback by default; never run an unauthenticated public listener. - Grant the smallest permission level; use Full control only when you need it.
- Never post pairing codes, QR codes, or connection strings publicly; each one works once, and none is a long-lived credential.
- Revoke devices you no longer use.
- A Relay only forwards encrypted traffic. It is not a permission boundary, and business data does not belong in its logs.
Troubleshooting first steps
Environment variables
The examples above use only the variables you cannot avoid. The full list ofvibex-server, Relay, and desktop variables, with defaults and purposes, is in the environment reference. Deployment forms, commands, and health checks are in Self-hosted headless runtime, and the Relay’s endpoints, limits, and push configuration are in Self-hosted Relay.
For deeper details on the pairing handshake, encryption, and sync contracts, read Remote v2 and Relay in the developer guide.