Traefik Integration
Traefik Integration
SNI Router is commonly deployed in front of one or more Traefik instances. This guide covers the two main integration points: SNI routing and PROXY protocol.
Basic setup — no PROXY protocol
If you do not need Traefik to see the real client IP, no special configuration is required on the Traefik side. SNI Router forwards the raw TLS stream and Traefik handles it normally.
# sni-router docker-compose.yml
environment:
SNI_ROUTE_1: "app1.example.com:192.168.1.10:443"
SNI_ROUTE_2: "app2.example.com:192.168.1.20:443"
SNI_DEFAULT: "192.168.1.10:443"
PROXY_PROTOCOL: "false"
PROXY protocol — real client IP forwarding
When PROXY_PROTOCOL=true, SNI Router prepends a PROXY protocol v2 header to every forwarded connection. This allows Traefik (and other backends) to extract the real client IP.
proxyProtocol and forwardedHeaders. Without this, Traefik receives non-TLS bytes first and the TLS handshake fails with SSL_ERROR_RX_RECORD_TOO_LONG.Enable PROXY protocol in SNI Router
# sni-router docker-compose.yml
environment:
SNI_ROUTE_1: "app1.example.com:192.168.1.10:443"
SNI_DEFAULT: "192.168.1.10:443"
PROXY_PROTOCOL: "true"
Configure Traefik — Docker Compose CLI args
# traefik docker-compose.yml
services:
traefik:
image: traefik:v3
command:
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.proxyProtocol.trustedIPs=10.0.0.0/24 # sni-router network
- --entrypoints.websecure.forwardedHeaders.trustedIPs=10.0.0.0/24
- --entrypoints.web.address=:80
- --entrypoints.web.proxyProtocol.trustedIPs=10.0.0.0/24
- --entrypoints.web.forwardedHeaders.trustedIPs=10.0.0.0/24
Replace 10.0.0.0/24 with the actual network range where SNI Router resides.
Configure Traefik — static YAML config
# traefik.yml
entryPoints:
websecure:
proxyProtocol:
trustedIPs:
- "10.0.0.1" # sni-router host IP
forwardedHeaders:
trustedIPs:
- "10.0.0.1"
web:
proxyProtocol:
trustedIPs:
- "10.0.0.1"
forwardedHeaders:
trustedIPs:
- "10.0.0.1"
HTTP challenge forwarding for Let's Encrypt
To forward Let's Encrypt http-01 ACME challenges to the correct Traefik instance, enable the HTTP frontend on SNI Router:
# sni-router docker-compose.yml
environment:
SNI_ROUTE_1: "app1.example.com:192.168.1.10:443"
SNI_ROUTE_2: "app2.example.com:192.168.1.20:443"
SNI_DEFAULT: "192.168.1.10:443"
SNI_HTTP_REDIRECT: "true"
HTTP_ROUTES: |
app1.example.com:192.168.1.10:80
app2.example.com:192.168.1.20:80
ports:
- "443:443"
- "80:80"
All http-01 challenge requests (/.well-known/acme-challenge/*) are forwarded to the matching Traefik instance. All other HTTP requests are 301-redirected to HTTPS.
Complete example
services:
sni-router:
image: ghcr.io/circle-rd/sni-router:latest
restart: unless-stopped
ports:
- "443:443"
- "80:80"
environment:
SNI_LISTEN_PORT: "443"
SNI_ROUTES: |
app1.example.com:192.168.1.10:443
app2.example.com:192.168.1.20:443
*.staging.example.com:192.168.1.30:443
SNI_DEFAULT: "192.168.1.10:443"
SNI_HTTP_REDIRECT: "true"
HTTP_ROUTES: |
app1.example.com:192.168.1.10:80
app2.example.com:192.168.1.20:80
PROXY_PROTOCOL: "true"