Getting started

From zero to a two-node mesh: install, configure a standalone node, add a route, then join a peer.

1. Install the daemon

Run the installer on every VPS you want in the fleet:

curl -fsSL https://bridgemesh.space/install.sh | sh

The installer places the binary in /usr/local/bin, creates a bridge system user and /etc/bridge, writes a minimal config if none exists, and enables a systemd service. See Install for details and manual installation.

2. Minimal standalone config

A single node runs fine on its own: omit the [node] section entirely and BRIDGE operates in standalone mode. Edit /etc/bridge/bridge.toml:

enable_telemetry = false

[proxy]
mode = "Direct"            # Direct | SniPassthrough | Managed
listeners = ["http"]
http_addr = "0.0.0.0:80"

[dashboard]
enabled = true
listen_addr = "127.0.0.1:9090"

[ipc]
enabled = true
socket_path = "/tmp/bridge.sock"

[logger]
level = "INFO"
format = "text"

Configuration is auto-discovered from ./bridge.toml, then $BRIDGE_CONFIG, then /etc/bridge/bridge.toml. TOML and YAML are both accepted.

3. Add your first route

Point a hostname at an upstream on this node by appending a [[services]] entry:

[[services]]
url = "https://app.example.com"
node_id = "node-01"
upstream = "127.0.0.1:3000"

In Direct mode the daemon reverse-proxies HTTP for that hostname to the upstream. Routes can also come from Docker auto-discovery: labeled containers become routes automatically when [discovery] is enabled.

4. Run it

If you used the installer, the service is already running:

systemctl status bridge
bridge status

Without systemd, run the daemon in the foreground:

bridge --config /etc/bridge/bridge.toml

5. Check the dashboard

Open http://127.0.0.1:9090 on the node. The embedded operations dashboard shows the node, its routes, and live events over a WebSocket stream. It binds to loopback by default.

6. Add a second node

To turn standalone nodes into a fleet, give each node a cluster identity and tell them about each other. On node-01:

# This node's cluster identity
[node]
id = "node-01"
mesh_ip = "10.8.0.1"
endpoint = "203.0.113.10:51820"
listen_port = 51820
priority = 100

[[nodes]]
node_id = "node-01"
endpoint = "203.0.113.10:51820"

On node-02, use its own identity and list node-01 as a seed so gossip has a starting point:

[node]
id = "node-02"
mesh_ip = "10.8.0.2"
endpoint = "203.0.113.11:51820"
listen_port = 51820
priority = 50

[[seeds]]
endpoint = "203.0.113.10:51820"

[[nodes]]
node_id = "node-01"
endpoint = "203.0.113.10:51820"

The WireGuard mesh comes up on the 10.8.0.x overlay; keys are auto-generated if not configured. The priority field feeds the bully election: the highest-priority alive node becomes leader and holds the ingress entrypoint. Restart both daemons after editing the config.

7. Watch the fleet converge

Within seconds, gossip membership converges. Confirm from either node:

bridge cluster

Both nodes appear in the dashboard's nodes and mesh views, one marked as leader. From here, pick an ingress handoff tier, tune configuration, and learn the day-two operations.