A single bridge.toml (or YAML) file describes the node, the proxy, and the fleet.
Config discovery
The daemon looks for its configuration in this order:
./bridge.toml: the current working directory
$BRIDGE_CONFIG: path from the environment variable
/etc/bridge/bridge.toml: the system location the installer uses
You can always override discovery with bridge --config /path/to/bridge.toml.
Both TOML and YAML are accepted. Omitting the [node] section runs the
daemon in standalone mode (no mesh, no election).
Full reference
# ==============================================================================# BRIDGE CONFIGURATION REFERENCE (bridge.toml)# ==============================================================================# Global telemetry reporting (anonymized error metrics). Disabled by default.
enable_telemetry = false
# ------------------------------------------------------------------------------# Logger Configuration# ------------------------------------------------------------------------------
[logger]
level = "INFO" # TRACE | DEBUG | INFO | WARN | ERROR
format = "text" # "text" for human-readable output, "json" for structured logs
target = "stderr" # "stderr" or "stdout"
ansi = true # ANSI color output in console logs# ------------------------------------------------------------------------------# Ingress Proxy Settings# ------------------------------------------------------------------------------
[proxy]
# Operating Modes:# "Managed" - Recommended for Coolify/Traefik. Bridge manages dynamic routes.# "Direct" - L7 reverse proxy. Bridge binds ports 80/443 and terminates TLS.# "Handoff" - L4 transparent passthrough with zero-copy TCP splicing & PROXY v2.
mode = "Managed"
# Target routing transport: "Mesh" (WireGuard overlay 10.8.0.x) or "Direct" (public IP)
routing = "Mesh"
# Maximum concurrency worker task ceiling (number or "auto" based on CPU cores)
max_concurrency = "auto"
# Listeners and bind addresses (used when mode = "Direct" or "Handoff")
listeners = ["http", "https"]
http_addr = "0.0.0.0:80"
https_addr = "0.0.0.0:443"
redirect_http = false # Redirect port 80 traffic to port 443# ------------------------------------------------------------------------------# Managed Mode Settings (Coolify / Traefik Dynamic Provider)# ------------------------------------------------------------------------------
[proxy.managed]
# Path to Traefik dynamic file (auto-detects /data/coolify/proxy/dynamic/bridge.yaml)# dynamic_config_path = "/data/coolify/proxy/dynamic/bridge.yaml"
local_node_id = "node-01" # Local routes skipped to let Traefik hit local containers directly
entrypoints = ["websecure"] # Traefik entrypoints to bind routers to
tls_enabled = true # Generate TLS router rules in Traefik
cert_resolver = "letsencrypt" # Traefik certificate resolver name
default_target_scheme = "http" # Target scheme for cross-node upstream servers
sync_interval = "5s" # Interval for syncing domain registry to Traefik
dashboard_domain = "bridge-dash.example.com" # Optional public dashboard domain
dashboard_upstream = "http://172.17.0.1:9090" # Host URL reachable from Traefik container# ------------------------------------------------------------------------------# Embedded Web Dashboard & Authentication# ------------------------------------------------------------------------------
[dashboard]
enabled = true
listen_addr = "0.0.0.0:9090" # Bind address (use 127.0.0.1:9090 for loopback only)
public_domain = "bridge-dash.example.com" # Optional leader-only public domain
[auth]
enabled = true # Enforce authentication for the dashboard# First-Run Setup Wizard: when enabled = true and [[auth.users]] is omitted,# the web UI at /login automatically presents an initial admin setup wizard.# Alternatively, pre-configure static users with Argon2 hashes:# [[auth.users]]# username = "admin"# password_hash = "$argon2id$v=19$m=65536,t=3,p=4$..."# ------------------------------------------------------------------------------# Unix Domain Socket IPC (Local CLI Control)# ------------------------------------------------------------------------------
[ipc]
enabled = true
socket_path = "/tmp/bridge.sock"
# ------------------------------------------------------------------------------# Docker Container Auto-Discovery# ------------------------------------------------------------------------------
[discovery]
enabled = true
docker_socket = "/var/run/docker.sock"
default_node_id = "node-01"
# ------------------------------------------------------------------------------# Cluster Identity & WireGuard Mesh Configuration# ------------------------------------------------------------------------------# (Omit the [node] block for standalone single-server mode)
[node]
id = "node-01"
endpoint = "203.0.113.10:51820" # Public endpoint peers dial
listen_port = 51820 # WireGuard listen port
mesh_ip = "10.8.0.1" # Address on the 10.8.0.0/24 overlay mesh
priority = 100 # Bully election priority (highest wins leadership)# ------------------------------------------------------------------------------# Bootstrap Cluster Seeds# ------------------------------------------------------------------------------
[[seeds]]
id = "node-01"
endpoint = "203.0.113.10:51820"
public_key = "BASE64_PUBLIC_KEY"
mesh_ip = "10.8.0.1"
# ------------------------------------------------------------------------------# Known Fleet Nodes & Target Backends# ------------------------------------------------------------------------------
[[nodes]]
id = "node-01"
endpoint = "203.0.113.10:80"
mesh_endpoint = "10.8.0.1:80"
[[nodes]]
id = "node-02"
endpoint = "203.0.113.11:80"
mesh_endpoint = "10.8.0.2:80"
# ------------------------------------------------------------------------------# Static Domain Services & Application Routing# ------------------------------------------------------------------------------
[[services]]
url = "https://app.example.com"
node_id = "node-01"
upstream = "127.0.0.1:3000"
# Workload Failover Duplication
[services.replicate]
enabled = true
image = "myorg/api:v1.2.0"
env = ["PORT=3000", "NODE_ENV=production"]
container_port = 3000
placement = "leader" # "ring" | "leader" | explicit node_id
failback_mode = "preemptive" # "preemptive" | "non_preemptive" | "manual"
failback_cooldown_secs = 10 # Flapping prevention cooldown# ------------------------------------------------------------------------------# Ingress Handoff & Failover (Tiers 2 & 3)# ------------------------------------------------------------------------------
[handoff]
mode = "none" # "none" | "dns" | "tunnel" | "floating_ip"# [handoff.tunnel]# token = "env:CF_TUNNEL_TOKEN"# warm_standby = false# [handoff.dns]# provider = "cloudflare"# zone_id = "YOUR_ZONE_ID"# record_name = "app.example.com"# api_token = "env:CF_API_TOKEN"# ------------------------------------------------------------------------------# Optional Sentry Error Monitoring# ------------------------------------------------------------------------------
[sentry]
# dsn = "env:SENTRY_DSN"
environment = "production"
sample_rate = 1.0
Sections
Top level
Key
Type
Description
enable_telemetry
boolean
Opt-in telemetry. Disabled by default.
[proxy]
Key
Type
Description
mode
string
Managed (dynamically configures Traefik / Coolify), Direct (L7 HTTP reverse proxy with TLS), or Handoff (L4 transparent passthrough with zero-copy TCP splice).
routing
string
Target transport preference: Mesh (WireGuard overlay 10.8.0.x) or Direct (public IP). Default Mesh.
max_concurrency
number | string
Worker concurrency ceiling (number or "auto"). Default 20.
listeners
array
Listener kinds to enable in Direct/Handoff modes, e.g. ["http", "https"].
http_addr
string
Bind address for HTTP ingress, e.g. 0.0.0.0:80.
https_addr
string
Bind address for HTTPS ingress, e.g. 0.0.0.0:443.
redirect_http
boolean
Redirect HTTP to HTTPS when both listeners are active.
Identifier of this node; local container routes are skipped so Traefik contacts them directly.
dynamic_config_path
string
Path to Traefik dynamic YAML file (auto-detects /data/coolify/proxy/dynamic/bridge.yaml).
entrypoints
array
Traefik entrypoints to bind routers to, e.g. ["websecure"].
tls_enabled
boolean
Generate TLS router configuration in Traefik. Default true.
cert_resolver
string
Traefik certificate resolver name, e.g. "letsencrypt".
default_target_scheme
string
Target scheme for cross-node upstream servers ("http" or "https").
sync_interval
string
Interval for synchronizing registry updates into Traefik's dynamic file, e.g. "5s".
dashboard_domain
string
Optional public domain to expose the leader's dashboard through Traefik.
dashboard_upstream
string
Explicit server URL for Traefik to reach the dashboard container/host, e.g. "http://172.17.0.1:9090".
[dashboard]
Key
Type
Description
enabled
boolean
Serve the embedded operations dashboard. Default true.
listen_addr
string
Bind address, e.g. 0.0.0.0:9090 or 127.0.0.1:9090 (loopback only).
public_domain
string
Optional public domain routed exclusively to the currently elected cluster leader.
[auth]
Authentication settings for the embedded dashboard.
Key
Type
Description
enabled
boolean
Enforce authentication for dashboard endpoints and UI. Default false.
users
array
Array of user tables with username and Argon2 PHC password_hash. When enabled = true and users is omitted or empty, the First-Run Web Setup Wizard automatically launches at /login to initialize the admin credentials.
[discovery]
Key
Type
Description
enabled
boolean
Watch Docker for labeled containers and turn them into routes automatically.
docker_socket
string
Path to the Docker socket, e.g. /var/run/docker.sock.
default_node_id
string
Node id assigned to discovered routes on this host.
[ipc]
Key
Type
Description
enabled
boolean
Serve the IPC socket the bridge CLI talks to.
socket_path
string
Default /tmp/bridge.sock.
[logger]
Key
Type
Description
level
string
Log level, e.g. INFO.
format
string
Output format, e.g. text.
[node]
Cluster identity for this node. Omit the whole section for standalone mode.
Key
Type
Description
id
string
Unique node identifier, e.g. node-01.
mesh_ip
string
This node's address on the WireGuard overlay, e.g. 10.8.0.1.
endpoint
string
Public address peers dial, host:port.
listen_port
number
WireGuard listen port, e.g. 51820. Keys are auto-generated if not configured.
priority
number
Bully election priority: higher wins leadership among alive nodes.
[[seeds]]
Key
Type
Description
endpoint
string
A peer endpoint gossip contacts first to join the fleet. Repeat the table for multiple seeds.
[[nodes]]
Key
Type
Description
node_id
string
Identifier of a known fleet member.
endpoint
string
Its public host:port endpoint.
[[services]]
Static routes. Repeat the table per service; discovered containers add routes alongside these.
Key
Type
Description
url
string
Public URL of the service, e.g. https://app.example.com.
node_id
string
Node hosting the upstream.
upstream
string
Backend address, e.g. 127.0.0.1:3000. Multiple targets across entries are spread by consistent-hash routing with session affinity.
[services.replicate]
Optional per-service failover duplication: when the hosting node fails, the
workload is spawned on a peer via the container driver.
Key
Type
Description
enabled
boolean
Turn on failover duplication for this service.
image
string
Container image spawned on the peer node.
env
table
Environment variables passed to the spawned container.
container_port
number
Port the container exposes.
placement
string
Placement rule selecting which peers may host the replica.
failback_mode
string
manual or automatic return of the workload once the original node recovers.
failback_cooldown_secs
number
Minimum time before failback runs, preventing flapping.
[handoff]
Key
Type
Description
mode
string
Ingress handoff tier: none, dns, tunnel, or floating_ip. See handoff tiers.
[handoff.tunnel]
Holds the Cloudflare Tunnel credentials used when mode = "tunnel".
The elected leader brings the tunnel up; on re-election the new leader takes it over.
[handoff.dns]
Holds the DNS provider configuration used when mode = "dns": the
provider credentials and record BRIDGE updates for health-checked DNS failover.
[sentry]
Optional error reporting.
Key
Type
Description
dsn
string
Sentry DSN.
environment
string
Environment tag attached to events, e.g. production.
sample_rate
number
Fraction of error events sent (0.0–1.0).
traces_sample_rate
number
Fraction of traces sent (0.0–1.0).
debug
boolean
Verbose Sentry SDK logging.
Environment variable:BRIDGE_CONFIG points the daemon at
a config file anywhere on disk and takes precedence over the system path. The
installer never overwrites an existing /etc/bridge/bridge.toml.