Skip to content

Using Traefik instead of Caddy

dockmesh’s embedded Caddy handles reverse proxy for most users, but if you already run Traefik or prefer its ecosystem (Let’s Encrypt via Cloudflare DNS-01, plugins, dashboard), you can use Traefik instead.

Disable the embedded Caddy (Settings → System → Reverse Proxy → Off) and run Traefik as a standalone stack:

services:
traefik:
image: traefik:v3
restart: unless-stopped
ports:
- "80:80"
- "443:443"
command:
- --api.dashboard=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.websecure.address=:443
- --certificatesresolvers.le.acme.httpchallenge=true
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.le.acme.email=${ACME_EMAIL}
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
labels:
- traefik.enable=true
- traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)
- traefik.http.routers.dashboard.entrypoints=websecure
- traefik.http.routers.dashboard.service=api@internal
- traefik.http.routers.dashboard.tls.certresolver=le
volumes:
letsencrypt:

Other stacks get Traefik labels to tell Traefik how to route them:

services:
nextcloud:
image: nextcloud:29
labels:
- traefik.enable=true
- traefik.http.routers.nextcloud.rule=Host(`cloud.example.com`)
- traefik.http.routers.nextcloud.entrypoints=websecure
- traefik.http.routers.nextcloud.tls.certresolver=le
- traefik.http.services.nextcloud.loadbalancer.server.port=80

Traefik picks up labels automatically via its Docker provider.

Option 2 — Traefik in front, Caddy behind (per-app TLS)

Section titled “Option 2 — Traefik in front, Caddy behind (per-app TLS)”

Some users want Traefik as the single public entrypoint but keep Caddy’s per-stack proxy config via dockmesh UI:

  1. Disable embedded Caddy’s public binding — bind to internal port only (e.g. 127.0.0.1:8000)
  2. Traefik points at host.docker.internal:8000 as backend
  3. Traefik handles public TLS, Caddy handles internal routing

This is more complex. Usually only makes sense in multi-dockmesh federated setups.

Traefik’s advantage over Caddy: simpler DNS-01 setup with many providers.

command:
...
- --certificatesresolvers.le.acme.dnschallenge=true
- --certificatesresolvers.le.acme.dnschallenge.provider=cloudflare
environment:
CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN}

Now you can get wildcard certs (*.example.com) without port 80 open.

Caddy (embedded)Traefik (stack)
SetupOne toggleFull stack deploy
UI integrationdockmesh Proxy tabTraefik dashboard separately
Per-route configdockmesh UIDocker labels
HTTPS automationACME HTTP-01 built-inHTTP-01 + DNS-01 via plugins
Plugins / middlewareCaddy’s nativeTraefik’s marketplace
Learning curveLowMedium-high

If you’re starting fresh: Caddy. If you’re coming from Traefik: Traefik.

With Traefik handling routing, the dockmesh UI’s “Proxy” tab is empty / not useful. dockmesh still:

  • Manages stack deployment (including Traefik itself)
  • Shows container health (Traefik’s dashboard shows router health too)
  • Handles TLS cert storage (in the Traefik volume, not dockmesh)

dockmesh doesn’t currently auto-inject Traefik labels when you add a “proxy route” in the UI — that’s a planned feature. For now, add labels manually in your compose files.