Traefik v3
Overview
Traefik is the single ingress point for all named HTTP/HTTPS traffic on Centerpoint.
It runs on the traefik-net Docker bridge network and discovers routes automatically
from container labels — no manual reload is needed when stacks are added or removed.
All TLS termination happens at Traefik; individual application containers serve plain
HTTP internally.
Access
| Type | URL / Endpoint | Notes |
|---|---|---|
| Dashboard | https://traefik.home.local |
Internal only — LAN access required |
The dashboard is exposed only on the internal Step-CA route. There is no external (internet-facing) route for the Traefik dashboard.
Configuration
Image: traefik:v3.6.13
Compose project: traefik (same project as step-ca)
Ports
| Port | Protocol | Purpose |
|---|---|---|
80 |
TCP | HTTP — auto-redirects all traffic to HTTPS |
443 |
TCP | HTTPS — primary entrypoint |
8080 |
TCP | Traefik API / Dashboard (internal) |
Static Configuration — traefik.yml
Location: /home/jeeves/docker/traefik/traefik.yml
Key settings:
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
network: traefik-net
exposedByDefault: false
file:
directory: /config
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: <redacted>
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
step-ca:
acme:
email: <redacted>
storage: /letsencrypt/step-ca.json
caServer: https://ca.home.local:9000/acme/acme/directory
certificatesDuration: 720
experimental:
plugins:
geoblock:
moduleName: github.com/PascalMinder/geoblock
version: v0.3.6
crowdsec-bouncer-traefik-plugin:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.3.0
Certificate Resolvers
| Resolver | Scope | Method | CA | Duration |
|---|---|---|---|---|
letsencrypt |
External (*.jeeves5454.ddns.net) |
HTTP challenge | Let's Encrypt | 90 days |
step-ca |
Internal (*.home.local) |
ACME | Internal Step-CA at ca.home.local:9000 |
30 days |
Plugins
| Plugin | Version | Purpose |
|---|---|---|
PascalMinder/geoblock |
v0.3.6 | Blocks requests from countries not in allowlist |
maxlerebourg/crowdsec-bouncer-traefik-plugin |
v1.3.0 | Forwards requests to CrowdSec bouncer for IP checks |
Geoblock is configured to allow CA, US, and IN only. The middleware is
named plex-geoblock@file and is defined in
/home/jeeves/docker/traefik/config/crowdsec.yml.
Dynamic Configuration
Location: /home/jeeves/docker/traefik/config/ (file-watched)
| File | Contents |
|---|---|
crowdsec.yml |
plex-geoblock and crowdsec-bouncer middleware defs |
dynamic.yml |
Static file-provider routes for Plex (no Docker labels) |
middlewares.yml |
Additional shared middleware definitions |
Standard Dual-Route Label Pattern
Each service that requires both internal and external access uses this label pattern
in its docker-compose.yml:
labels:
- "traefik.enable=true"
# External route — Let's Encrypt TLS + security middleware
- "traefik.http.routers.<name>-ext.rule=Host(`<svc>.jeeves5454.ddns.net`)"
- "traefik.http.routers.<name>-ext.entrypoints=websecure"
- "traefik.http.routers.<name>-ext.tls.certresolver=letsencrypt"
- "traefik.http.routers.<name>-ext.middlewares=authentik-auth@docker,plex-geoblock@file,crowdsec-bouncer@file"
# Internal route — Step-CA TLS, no SSO middleware
- "traefik.http.routers.<name>-int.rule=Host(`<svc>.home.local`)"
- "traefik.http.routers.<name>-int.entrypoints=websecure"
- "traefik.http.routers.<name>-int.tls.certresolver=step-ca"
# Backend
- "traefik.http.services.<name>-svc.loadbalancer.server.port=<port>"
Volumes / Bind Mounts
| Host Path | Container Path | Purpose |
|---|---|---|
/home/jeeves/docker/traefik/traefik.yml |
/traefik.yml |
Static config |
/home/jeeves/docker/traefik/config |
/config |
Dynamic config (file-watched) |
/home/jeeves/docker/traefik/letsencrypt |
/letsencrypt |
ACME certificate storage |
/var/log/traefik |
/var/log/traefik |
Access logs (JSON) |
/var/run/docker.sock |
/var/run/docker.sock |
Docker label discovery |
Dependencies
traefik-netDocker network (must be created manually before first start)step-cacontainer (must be healthy for internal certs to renew)- CrowdSec LAPI at
crowdsec:8080(bouncer requires it; Traefik starts without it but will error on blocked requests)
Notes / Gotchas
traefik-netis externally managed — always create it first:docker network create traefik-net- Traefik discovers routes from container labels only on containers attached to
traefik-net. If a container is not on this network it will be invisible to Traefik even withtraefik.enable=true. exposedByDefault: falsemeans every service must explicitly opt in withtraefik.enable=true.- The
step-cacertificate resolver stores its ACME account and certs in/letsencrypt/step-ca.json(separate from the Let's Encrypt storage). Do not delete this file or certificates will be re-issued from scratch. - Access logs are written to
/var/log/traefik/access.login JSON format and are also bind-mounted into the CrowdSec container for log ingestion.
Last Updated: 2026-06-16