Multi-node Deployment Guide

From bare VMs to an encrypted, self-aware fleet: how nodes get their mesh IP, bootstrap WireGuard, elect an edge leader, and route cross-fleet traffic.

How nodes get their mesh IP

BRIDGE creates a decentralized Layer 3 overlay network directly inside the Linux kernel. Unlike legacy VPNs or centralized SD-WANs, there is no central controller or hub-and-spoke bottleneck:

Subnet design

1. Overlay subnet

The cluster operates on a private subnet (conventionally 10.8.0.0/24). Each node is assigned a unique IP within this range via mesh_ip.

Kernel interface

2. WireGuard interface (wg0)

On startup, BRIDGE creates and provisions the wg0 interface using CAP_NET_ADMIN, binding mesh_ip/24 on port 51820.

Crypto keys

3. Curve25519 keypairs

Each node generates an RFC 7748 Curve25519 keypair automatically if not explicitly configured in bridge.toml.

Routing table

4. Point-to-point routes

When SWIM gossip discovers a peer, BRIDGE programs a kernel peer route with AllowedIPs = [<peer_mesh_ip>/32] pointing to that peer's public UDP endpoint.

Traffic routed across nodes flows directly point-to-point over WireGuard at kernel speed. If node-01 needs to send a request to a container running on node-02, it sends packets to 10.8.0.2, which tunnel securely over UDP without transit through an intermediary.

Prerequisites & Firewall

Before installing, ensure each VM can reach peers on the required ports:

Port / ProtocolDirectionPurpose
80 / TCP, 443 / TCPInbound (Public)Ingress HTTP/HTTPS traffic from clients.
51820 / UDPInbound / Outbound (Inter-node)Encrypted WireGuard mesh tunnels and SWIM gossip heartbeats.
9090 / TCPLocalhost / PrivateEmbedded operations console, JSON API, and WebSocket event stream.

Step 1: Install BRIDGE on each VM

Run the installation script on all nodes you want in the cluster (e.g. node-01, node-02, node-03):

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

Direct GitHub raw fallback: curl -fsSL https://raw.githubusercontent.com/Penivera/Bridge/main/scripts/install.sh | sh

The installer configures /usr/local/bin/bridge, sets up the dedicated bridge system user with CAP_NET_BIND_SERVICE and CAP_NET_ADMIN, and provisions a systemd unit.

Step 2: Configure the bootstrap node (node-01)

Designate your first node (e.g. node-01 on public IP 203.0.113.10) as the bootstrap seed and edge leader. Edit /etc/bridge/bridge.toml:

enable_telemetry = false

[proxy]
mode = "Direct"
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"

# This node's cluster identity and mesh address
[node]
id = "node-01"
mesh_ip = "10.8.0.1"
endpoint = "203.0.113.10:51820"
listen_port = 51820
priority = 100               # Highest priority: elected leader for public ingress

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

Validate the syntax and start the daemon:

bridge config validate --config /etc/bridge/bridge.toml
systemctl restart bridge

Step 3: Join worker nodes to the mesh

On your other VMs (node-02 at 203.0.113.11 and node-03 at 203.0.113.12), assign unique mesh IPs (10.8.0.2 and 10.8.0.3) and point them at node-01 in [[seeds]]:

# /etc/bridge/bridge.toml on node-02
enable_telemetry = false

[proxy]
mode = "Direct"
listeners = ["http"]
http_addr = "0.0.0.0:80"

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

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

[[nodes]]
node_id = "node-02"
endpoint = "203.0.113.11:51820"

On node-03, apply the same structure with mesh_ip = "10.8.0.3", its public endpoint, and priority = 60. Restart the service on each host:

systemctl restart bridge

Step 4: Verify the fleet using the CLI

Inspect cluster health, mesh interfaces, and leader election using BRIDGE CLI commands:

# 1. Check overall system health
bridge health

# 2. List nodes, mesh IPs, and elected roles
bridge nodes

# 3. Inspect WireGuard mesh interface and active tunnels
bridge mesh status

# 4. Check leader election consensus
bridge election status

You should see all 3 nodes marked ALIVE, connected over wg0, with node-01 elected as the active leader holding the public ingress boundary.

Step 5: Add routes & test cross-fleet traffic

Define a service running on node-02 (e.g. a web application listening on local port 3000):

bridge add-route app.example.com --upstream 127.0.0.1:3000 --node-id node-02

Now test traffic from your laptop or public client by sending a request to the leader's public IP:

curl -H "Host: app.example.com" http://203.0.113.10/

The request reaches node-01, matches the routing table for app.example.com, and tunnels instantaneously across the WireGuard mesh to node-02 (10.8.0.2:3000).

Step 6: Test autonomous failover

Simulate an edge failure by stopping node-01 (or triggering a step-down):

bridge election trigger

SWIM gossip detects the change, Bully consensus executes in milliseconds, and node-02 (the highest-priority alive peer) assumes leadership and takes over the ingress entrypoint automatically. No human intervention, no stale DNS.