Ingress & Reverse Proxy
Broch listens on HTTP internally (port 8080) and does not terminate TLS itself. Every deployment needs a reverse proxy (ingress) in front of it to handle TLS termination and forward requests to the server.
This is not optional — your wildcard TLS certificate is attached to the ingress, not to Broch directly.
Per-Platform Ingress
Section titled “Per-Platform Ingress”| Platform | Ingress | Notes |
|---|---|---|
| Docker Compose | Any reverse proxy — run alongside Docker Compose or external | Caddy can provision and renew the wildcard certificate automatically via DNS-01 |
| DigitalOcean (Terraform) | Any reverse proxy — run alongside Docker Compose or external | The provided Terraform configuration uses Caddy, which provisions and renews the wildcard certificate automatically via DNS-01 |
| Azure Container Apps | Built-in ACA ingress, Azure Application Gateway, or Azure Load Balancer | Adding an Application Gateway or Load Balancer in front of ACA narrows the Trusted Proxy CIDR to a much smaller, well-defined IP range |
| AWS | Application Load Balancer, Network Load Balancer, or CloudFront | Using a load balancer narrows the Trusted Proxy CIDR to a much smaller, well-defined IP range |
What the Ingress Must Do
Section titled “What the Ingress Must Do”Regardless of which ingress you use, it must:
- Terminate TLS for
*.your-wildcard-hostnameandyour-wildcard-hostname - Forward all traffic to Broch on port 8080
- Pass
X-Forwarded-For,X-Forwarded-Proto, andHostheaders - Support WebSocket upgrades (
Upgrade: websocket,Connection: upgrade) — tunnel connections use WebSockets - Briefly retry the connection to Broch when it is momentarily unavailable — a restart or image upgrade — instead of returning an immediate 502
If you bring your own reverse proxy (Docker Compose BYO cert option), verify these headers are forwarded correctly. Missing WebSocket support will prevent tunnels from connecting.
Surviving Restarts
Section titled “Surviving Restarts”Broch is a single process. Restart it — docker compose up -d, an image upgrade — and it is unreachable for a second or two. An ingress that forwards once and gives up turns that into a user-visible 502. An ingress that briefly retries the connection holds the request until Broch is back.
The bundled Caddy templates do this:
reverse_proxy broch:8080 { header_up Host {host} lb_try_duration 30s lb_try_interval 250ms}Bringing your own proxy? Configure an equivalent connect-retry — nginx proxy_next_upstream error timeout with proxy_next_upstream_tries, or a load balancer’s health checks plus connection draining. This covers Broch being briefly unreachable; it does not change how a 5xx that Broch itself returns is handled.
On a managed platform this is automatic — you configure nothing. A fronting load balancer or edge (Azure Front Door, Azure Application Gateway, or the Azure Container Apps ingress; on AWS, an Application Load Balancer with target health checks and connection draining, or CloudFront) health-checks a pool of instances and routes around whichever one is restarting, draining its in-flight connections first. The single-VM Caddy setup has only one Broch instance — it can’t route around a restart, so lb_try_duration makes it wait one out instead.
Trusted Proxy CIDRs
Section titled “Trusted Proxy CIDRs”Because Broch sits behind a reverse proxy, the IP address it sees on incoming connections is the proxy’s IP, not the client’s. Broch reads the real client IP from the X-Forwarded-For header — but only from proxies it trusts.
A proxy on the same machine as Broch (loopback) is trusted automatically — no configuration needed. For a proxy on a different host or container (Docker bridge, load balancer), configure Trusted Proxy CIDRs in the admin dashboard under Share → Trusted Proxy CIDRs, set to the IP range of your reverse proxy or load balancer.
| Platform | What to set |
|---|---|
| Docker Compose (same host) | 172.16.0.0/12 (Docker bridge network) |
| DigitalOcean | 10.0.0.0/8 or the Droplet’s internal network |
| Azure Container Apps | The ACA internal VNET range |
| AWS ALB | The ALB subnet CIDRs |
The Trusted Proxy CIDRs card auto-detects the ingress IP the server currently sees, flags whether it’s covered by your configured CIDRs, and suggests a range — use Re-detect ingress to refresh it.
Why this matters: If a non-loopback proxy isn’t trusted, Broch can’t distinguish the real client IP from the proxy’s. Share Policy rules that use Network (IP/CIDR) conditions then fail closed — they deny (the server logs a warning, and the Networks tab stays disabled until a proxy is detected), and audit logs record the proxy IP instead of the client’s. Policies without network conditions — header-based or allow-all — are unaffected. So this is about IP-based access control and attribution, not tunnel availability in general.