Skip to content

Docker Compose Deployment behind Traefik Reverse Proxy

Snawoot edited this page Aug 5, 2025 · 14 revisions

This example exposes dumbproxy via Traefik reverse proxy, routing connections by domain in SNI of TLS handshake. TLS connection is handled on Traefik side, dumbproxy gets plaintext HTTP connection. Original client address is preserved and passed to dumbproxy (-proxyproto option).

Full configuration files are provided for context, but the gist of it is these service labels defining how service should be exposed:

        traefik.enable: "true"
        traefik.tcp.routers.dumbproxy.service: dumbproxy
        traefik.tcp.routers.dumbproxy.rule: HostSNI(`<your-domain>`)
        traefik.tcp.routers.dumbproxy.tls: "true"
        traefik.tcp.routers.dumbproxy.tls.passthrough: "false"
        traefik.tcp.routers.dumbproxy.tls.certResolver: letsencrypt
        traefik.tcp.services.dumbproxy.loadBalancer.server.port: 8080
        traefik.tcp.services.dumbproxy.loadbalancer.proxyProtocol.version: 2

Everything else is a typical deployment of Traefik in Docker Compose, see up to date documentation for Traefik you're using.

Important

Don't forget to replace <your-domain.com> and <your-email> with corresponding literal values.

docker-compose.yaml:

networks:
  traefik:

services:
  dumbproxy:
    image: ghcr.io/senseunit/dumbproxy:1.27.0
    command:
      - -bind-address=:8080
      - -proxyproto
    deploy:
      labels:
        traefik.enable: "true"
        traefik.tcp.routers.dumbproxy.service: dumbproxy
        traefik.tcp.routers.dumbproxy.rule: HostSNI(`<your-domain>`)
        traefik.tcp.routers.dumbproxy.tls: "true"
        traefik.tcp.routers.dumbproxy.tls.passthrough: "false"
        traefik.tcp.routers.dumbproxy.tls.certResolver: letsencrypt
        traefik.tcp.services.dumbproxy.loadBalancer.server.port: 8080
        traefik.tcp.services.dumbproxy.loadbalancer.proxyProtocol.version: 2
    networks:
      traefik:

  traefik:
    image: traefik:v3.5.0
    networks:
      traefik:
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik.yaml:/etc/traefik/traefik.yaml
      - ./dynamic.yaml:/etc/traefik/dynamic.yaml
      - ./acme.json:/etc/traefik/acme.json

/etc/traefik/traefik.yaml:

providers:
  [swarm|docker]:
    exposedByDefault: false
    endpoint: unix:///var/run/docker.sock
    network: traefik
    watch: true
  file:
    filename: /etc/traefik/dynamic.yaml
    watch: true

api:
  dashboard: false

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true

  websecure:
    address: :443
    forwardedHeaders:
      insecure: true
    http:
      tls:
        certResolver: letsencrypt

certificatesResolvers:
  letsencrypt:
    acme:
      email: <your-email>
      storage: /etc/traefik/acme.json
      tlsChallenge: {}

/etc/traefik/dynamic.yaml:

tls:
  options:
    default:
      minVersion: VersionTLS12
      maxVersion: VersionTLS13
      sniStrict: true
      curvePreferences:
        - CurveP521
        - CurveP384
      alpnProtocols:
        - http/1.1
        - h2
        - acme-tls/1
Clone this wiki locally