-
Notifications
You must be signed in to change notification settings - Fork 55
Docker Compose Deployment behind Traefik Reverse Proxy
Snawoot edited this page Jul 30, 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
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.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:
- db-data:/var/lib/backup/data
- /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.jsonconfigs/traefik.yaml:
global:
checkNewVersion: false
sendAnonymousUsage: false
log:
level: INFO
noColor: false
filePath: /dev/stdout
accessLog:
filePath: /dev/stdout
providers:
swarm:
exposedByDefault: false
endpoint: unix:///var/run/docker.sock
network: traefik_proxy
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
middlewares:
- default@file
certificatesResolvers:
letsencrypt:
acme:
email: <your-email>
storage: /etc/traefik/acme.json
tlsChallenge: {}configs/dynamic.yaml:
tls:
options:
default:
minVersion: VersionTLS12
maxVersion: VersionTLS13
sniStrict: true
curvePreferences:
- CurveP521
- CurveP384
alpnProtocols:
- http/1.1
- h2
- acme-tls/1
http:
middlewares:
default:
headers:
browserXssFilter: true
referrerPolicy: strict-origin-when-cross-origin
stsPreload: true
sslRedirect: true
sslTemporaryRedirect: true
sslForceHost: true
stsSeconds: "31536000"
forceSTSHeader: true
frameDeny: true
contentSecurityPolicy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'
contentSecurityPolicyReportOnly: default-src 'self'; script-src 'self' 'nonce-{random}'
contentTypeNosniff: true
customResponseHeaders:
X-Forwarded-Server: traefik
Permissions-Policy: camera=(), microphone=(), geolocation=()
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin