Guides

Traefik Integration

How to use SNI Router with Traefik, including PROXY protocol configuration.

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.

Traefik must trust the SNI Router's IP for both 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"
Copyright © 2026