diff --git a/traefik-reference.yml b/traefik-reference.yml new file mode 100644 index 0000000..ac30ad8 --- /dev/null +++ b/traefik-reference.yml @@ -0,0 +1,84 @@ +# Reference Traefik stack configuration for Docker Swarm. +# This is NOT deployed by this project — it documents the Traefik setup +# that the tunnel-server depends on for dynamic routing via Swarm labels. +# +# Key requirements: +# - Docker Swarm provider enabled (--providers.docker.swarmMode=true) +# - Exposed by default OFF (--providers.docker.exposedbydefault=false) +# - A shared overlay network (e.g. "traefik") +# - An ACME cert resolver for automatic TLS +# - NO file providers — all routing is done via Docker service labels +# +# Deploy: docker stack deploy -c traefik-reference.yml traefik + +networks: + traefik: + external: true + +services: + traefik-http: + image: traefik:v2 + command: + - --providers.docker.endpoint=unix:///var/run/docker.sock + - --providers.docker.swarmMode=true + - --providers.docker.exposedbydefault=false + - --providers.docker.network=traefik + - --serverstransport.insecureskipverify=true + - --log.level=ERROR + - --global.checknewversion=false + - --global.sendanonymoususage=false + - --entrypoints.web.address=:80 + - --entrypoints.websecure.address=:443 + - --entrypoints.web.http.redirections.entryPoint.to=websecure + - --entrypoints.web.http.redirections.entryPoint.scheme=https + - --entrypoints.web.http.redirections.entryPoint.permanent=true + - --entryPoints.websecure.forwardedHeaders.insecure=true + - --entryPoints.websecure.transport.respondingTimeouts.idleTimeout=600s + - --entryPoints.websecure.transport.respondingTimeouts.readTimeout=600s + - --entryPoints.websecure.transport.respondingTimeouts.writeTimeout=600s + - --certificatesresolvers.letsencryptresolver.acme.httpchallenge=true + - --certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web + - --certificatesresolvers.letsencryptresolver.acme.email=admin@example.com + - --certificatesresolvers.letsencryptresolver.acme.storage=/letsencrypt/acme.json + - --api.dashboard=true + ports: + - target: 80 + published: 80 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: udp + mode: host + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - traefik-letsencrypt:/letsencrypt + networks: + - traefik + deploy: + endpoint_mode: dnsrr + replicas: 1 + placement: + constraints: + - node.role == manager + labels: + traefik.enable: "true" + traefik.docker.network: "traefik" + traefik.http.routers.traefik-dashboard.rule: "Host(`traefik.example.com`)" + traefik.http.routers.traefik-dashboard.entrypoints: "websecure" + traefik.http.routers.traefik-dashboard.tls: "true" + traefik.http.routers.traefik-dashboard.tls.certresolver: "letsencryptresolver" + traefik.http.routers.traefik-dashboard.service: "api@internal" + traefik.http.services.traefik-dashboard.loadbalancer.server.port: "888" + update_config: + order: stop-first + failure_action: rollback + restart_policy: + condition: on-failure + +volumes: + traefik-letsencrypt: