All writing
Project Log 1 min read
Homelab Notes: Running Services Behind Traefik
My current homelab setup, why I moved off nginx-proxy, and what broke along the way.
Spent the weekend migrating my homelab reverse proxy from nginx-proxy to Traefik v3. Here's what I ended up with.
The stack
- Mini PC, Debian 12, Docker Compose
- Traefik v3 as the single entrypoint on 80/443
- Cloudflare origin certificates for public services
- Step-CA for internal
*.labcerts - ~18 services, from Home Assistant to a self-hosted Postgres
Why I moved
nginx-proxy was fine until I wanted per-service middleware (rate limiting, auth forwarding, compression). Adding it to nginx-proxy means templating; Traefik treats middleware as first-class labels.
The compose pattern I settled on
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx
labels:
- traefik.enable=true
- traefik.http.routers.paperless.rule=Host(\`paperless.lab\`)
- traefik.http.routers.paperless.entrypoints=websecure
- traefik.http.routers.paperless.tls=true
- traefik.http.routers.paperless.middlewares=forward-auth@file
- traefik.http.services.paperless.loadbalancer.server.port=8000
networks: [edge]
yaml
Every service gets those six labels. Middleware chains live in a shared dynamic.yml.
What broke
- Websockets needed explicit
passHostHeader=trueon the router. - One service shipped a healthcheck that returned 301. Traefik marked it unhealthy. Added
--providers.docker.useBindPortIP=falseand overrode the service port. - Cloudflare tunnel + Traefik is a footgun: double TLS termination works but you want
insecureSkipVerifyoff the internal hop.
Next
Wire Authentik as the forward-auth provider for everything internal. Kill the last plaintext basic-auth config.
Keep going
Where to next?
Browse more technical writing, see the engineering case studies, or reach out directly.