CallMeTechie
DE Login
Home Products Blog About Contact

Gateway Pool: Enable Load Balancing

⚙️ Advanced · Updated 1 month ago

Load Balancing Mode in Detail

Activation

A route uses LB only when all three conditions are true:

  1. route.target_pool_id is set (NOT target_peer_id)
  2. Pool mode = 'load_balancing'
  3. Pool lb_policy ∈ {round_robin, least_conn, ip_hash}

Caddy Configuration (HTTP)

During the build cycle, caddyConfig.resolveRouteUpstreams calls gatewayPool.resolveActivePeers(snapshot) — which returns all alive pool members:

"reverse_proxy": {
  "upstreams": [
    { "dial": "10.8.0.2:18080" },
    { "dial": "10.8.0.8:18080" }
  ],
  "load_balancing": {
    "selection_policy": { "policy": "round_robin" }
  },
  "health_checks": {
    "passive": {
      "fail_duration": "30s",
      "max_fails": 3,
      "unhealthy_status": [500, 502, 503, 504]
    }
  }
}

LB Policies

Policy Behavior When to use
round_robin Round-robin through the upstream list Symmetric load, identical members
least_conn Member with fewest active connections Long streams (Jellyfin streaming, backups)
ip_hash Hash over client IP → fixed member Session affinity without cookies (legacy apps)

Trusted Proxies (for ip_hash behind a CDN/LB)

If GateControl sits behind a private LB or a CDN, the server Caddy only sees the proxy IP as the remote IP — ip_hash would then be ineffective (all requests hit the same bucket). The workaround is built into the srv0 HTTP server:

{
  "trusted_proxies": {
    "source": "static",
    "ranges": [
      "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16",
      "100.64.0.0/10", "fd00::/8", "::1/128", "127.0.0.0/8"
    ]
  },
  "client_ip_headers": ["X-Forwarded-For"]
}

X-Forwarded-For is only honored when the connection originates from one of the listed ranges. Clients hitting GateControl directly from the internet cannot spoof XFF, because their source IP is not in the trust list.

Passive Health Checks

In addition to the gatewayHealth watchdog (every 30 s), Caddy itself checks passively:

  • Sends a request to member X
  • X returns a 5xx status (or fails to connect)
  • After max_fails=3 such failures, X is removed from rotation for fail_duration=30s
  • After 30 s, retried

This makes circuit breaking kick in within seconds, instead of waiting for the global health logic's 90 s gateway_down_threshold.

L4 Load Balancing (TCP/UDP)

Works the same way for L4 routes — caddy-l4's proxy handler accepts multiple upstreams[] plus load_balancing.selection_policy:

{
  "handler": "proxy",
  "upstreams": [
    { "dial": ["10.8.0.2:13389"] },
    { "dial": ["10.8.0.8:13389"] }
  ],
  "load_balancing": {
    "selection_policy": { "policy": "round_robin" }
  },
  "health_checks": {
    "passive": { "fail_duration": "30s", "max_fails": 3 }
  }
}

L4 routes must have route_type='l4' and be pool-bound via target_pool_id.


Cookie Settings

We use cookies to improve your experience. Essential cookies are always active.

Privacy Policy
ESC
↑↓ navigate open esc close