How to Install Traefik on Docker Swarm with Certificates
Table of contents
- Key takeaways
- What needs to be in place before starting
- The network over which services talk
- Certificates: HTTP challenge or DNS challenge
- The certificate store
- Static and dynamic configuration
- The dashboard: useful but must be protected
- The first service behind Traefik
- Middlewares: where policy lives
- What you'll forget the first time
- Conclusion
- Sources
Updated: 2026-07-07
Traefik is the default reverse proxy for Docker Swarm: automatic service discovery via labels, Let's Encrypt certificates with DNS challenge, and reusable middleware chains. This guide covers the overlay network, static and dynamic configuration, certificate storage for multi-manager setups, and the production decisions that actually matter.
Traefik[1] has become, almost by osmosis, the default reverse proxy in Docker Swarm environments: label-driven declarative config, nearly transparent Let’s Encrypt certificates, and a dashboard that makes routing understandable. This guide is aimed at the moment you move from "works on my laptop" to "this has to receive real traffic" — a less trivial jump than it seems.
Key takeaways
-
The
traefik_publicoverlay network is the join point between Traefik and the services it proxies. -
The DNS-01 challenge is preferred in production: it allows wildcards and frees port 80 during validation.
-
A single-node local volume cert store fails when you scale to a second manager.
-
The dashboard contains sensitive information: never expose it without strong authentication.
-
Middlewares in reusable chains (
chain-base,chain-oauth) are what keep the config manageable.
What needs to be in place before starting
Four things should be resolved before running a single command in a Docker Swarm cluster[2]:
-
An initialized Swarm cluster, even with a single node.
-
A domain whose record points to the manager’s public IP.
-
An API token at your DNS provider with permission to create TXT records.
-
An email address for Let’s Encrypt.
Ports 80 and 443 must be open toward the manager. This sounds obvious but is one of the most common causes of initial errors: a misconfigured firewall, a cloud provider that blocks port 80 by default, or a security group applied to the wrong node.
The network over which services talk
Traefik needs an overlay network shared with the services it proxies. Creating it is a one-time step:
docker network create --driver=overlay --attachable traefik_public
The --attachable flag lets containers outside a Swarm service connect to it too. From here, any service that declares traefik_public as one of its networks is automatically discoverable by Traefik.
Certificates: HTTP challenge or DNS challenge
The DNS-01 challenge is almost always the right choice for production. Let’s Encrypt[3] issues free certificates every 90 days; DNS-01:
-
Frees Traefik from having to receive traffic on port 80 during validation.
-
Allows wildcard certificates (
*.example.com), handy when you will run dozens of subdomains.
HTTP-01 suffices if you only need certs for a domain already pointed at the server and do not need wildcards. For Cloudflare, the DNS-01 challenge passes two environment variables to the service (your email and an API token with limited permissions). Within seconds Traefik requests the cert, the provider creates the TXT record, Let’s Encrypt validates, and the certificate is issued.
The certificate store
Let’s Encrypt issues certificates every 90 days and Traefik renews them automatically, keeping them in a JSON file on disk. This is the most often-overlooked detail:
-
For a single manager, a Docker volume suffices.
-
For multiple managers, the file must be on shared storage (NFS, GlusterFS, JuiceFS).
If the Traefik service moves from one node to another with a local volume, it will request certificates from scratch. Let’s Encrypt has rate limits you will hit quickly. If you anticipate growing, solve it from the start.
Static and dynamic configuration
The official Traefik documentation[4] splits config into two planes:
-
Static: things that do not change hot (discovery providers, entrypoints, cert resolvers, logging). Lives in
traefik.yml. -
Dynamic: routes, middlewares, services. Lives in each service’s labels.
The static config is mounted as a read-only volume in the Traefik compose file. There you declare the ACME resolver with its DNS challenge, the two entrypoints (web for 80, websecure for 443), the Docker Swarm provider, and the dashboard. Nothing conceptually hard, just a convention that clicks after reading it once carefully.
The dashboard: useful but must be protected
The dashboard shows active routes, applied middlewares, and service state. The temptation to leave it publicly exposed is real; resist it.
Two approaches work:
-
Make it accessible only through internal networking (e.g., WireGuard) without exposing it through Traefik.
-
Expose it protected by strong authentication: OAuth via Authentik, Keycloak, or at least basic auth with non-trivial credentials.
The dashboard gives an attacker a complete map of your infrastructure. This is also the pattern the jacar.es stack uses to protect internal tooling.
The first service behind Traefik
Once Traefik is deployed, exposing a service is purely declarative. The minimum pattern in the service compose file:
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
- "traefik.http.services.myapp.loadbalancer.server.port=8080"
Traefik discovers labels automatically as soon as the service deploys, requests the certificate if needed, and starts routing. That automatic discovery is what drives the popularity: the config lives alongside the service it configures, not in a central file.
Middlewares: where policy lives
The most useful middlewares in production:
-
HTTP-to-HTTPS redirection: 301 redirect for every port-80 request.
-
Security headers:
Strict-Transport-Security,X-Frame-Options, and similar on every response. -
Compression: gzip and brotli automatically.
-
IP rate limiting: dampens spikes and basic attacks.
-
Forward auth: delegates authentication to Authentik or similar.
Define chains that group common middlewares: a chain-base for everything public, a chain-oauth adding forward auth for dashboards and internal tools. This composition pattern also works well in GitOps environments with Flux to keep policy separate from infrastructure definitions.
What you’ll forget the first time
Common oversights:
-
Default
logLevelis too verbose for production; dropping toINFOcuts noise without losing useful signal. -
JSON-format access log piped to Loki or Elasticsearch is enormously valuable for debugging routing issues.
-
Prometheus metrics are off by default; enabling them is one line in the static config.
-
Traefik’s default certificate authority, if you do not declare one, is Let’s Encrypt’s staging environment, which issues certificates that browsers do not trust. Explicitly declare the production CA in your ACME resolver.
Conclusion
Traefik wins comfortably in environments with many small services changing often, which is exactly most Swarm stacks: label config, native Docker integration, and automatic certificates are the winning combo. Start with the minimum, do not activate the dashboard without authentication, add middlewares as you actually need them. And when things grow, take shared cert-store storage seriously — it is the kind of decision that, made badly, haunts you through the first scale-up.