withvibe
Self-hosting

Network isolation

When many people run many envs on one host, you don't want one env able to reach another's database by name. withvibe isolates every env on its own Docker network by default. This page explains the model and the controls.

One network per env

Each env runs as its own Docker Compose project, named withvibe-<envId>, with its own default network. Services inside an env share that network and can reach each other by name — but that name only resolves within the env. A service in one env cannot resolve or reach a service in another env.

The core property
Separate per-env networks mean no cross-env name resolution. Env A's dbis invisible to env B — there's no shared flat network where a bare service name leaks across tenants.

What bridges across envs

In subdomain routing mode, each env also gets a dedicated edge network (withvibe-<envId>-edge), and Traefik is the only thing connected across envs — and only to services explicitly exposed through it (traefik.enable=true). Public traffic reaches an env's exposed services through Traefik on that edge network; nothing else crosses the boundary.

In port mode, there's no edge network at all — envs publish host ports instead, and isolation is simply the per-env network with no shared bridge.

How sidecars attach

Sidecars — the Claude runner, the QA browser, code-server, the database viewer, and plugin containers — join the env's ownnetwork, so they get in-env DNS to that env's services (and only that env's). They're reaped when the env stops. None of this needs configuration; it's automatic per env.

The compose security gate

User-supplied compose files are checked before they run, and several rules exist specifically to protect the isolation boundary:

  • External networks are rejected, except the configured proxy network and the env's own edge network. You can't attach a service to some other shared network to get around isolation.
  • Private services can't sit on a shared network.Only Traefik-exposed services may ride the shared/edge net — because Docker registers a service's name as a DNS alias on every network it joins, a private database left on a shared net would be reachable by name from other envs.
  • Host-escape vectors are blockedprivileged, cap_add, devices, host namespaces, network_mode: host, and bind mounts that resolve outside the env's own directory are all rejected. The gate resolves the fully-rendered compose and fails closed.

Operator configuration

Baseline isolation is automatic — you configure nothing for it. A few environment variables exist around the edges:

  • PROXY_NETWORK — the name of the shared Traefik proxy network (default proxy).
  • WITHVIBE_TRAEFIK_CONTAINER— overrides Traefik container discovery if auto-detection picks the wrong one. If Traefik can't be attached, envs 504 until it's fixed, and the failure is logged loudly.
  • Cross-env shared infrastructure (opt-in, fail-closed) — if you genuinely need a service shared across specific envs (e.g. a common database), the operator sets WITHVIBE_SHARED_NET plus an allowlist of authorized envs/templates (WITHVIBE_SHARED_ENVS / WITHVIBE_SHARED_TEMPLATES). A compose service requests it with x-use-shared, but that request grants nothing on its own — only allowlisted envs are connected. Leave these unset and cross-env sharing is fully disabled.
This is isolation, not a sandbox boundary
Network isolation stops envs from reaching each other over the network. It is not a substitute for the Docker socket precautions in the self-host overview — the API still orchestrates Docker, so run it on a host you treat as privileged.