Traefik
Traefik
Reverse proxy, která se konfiguruje sama podle štítků kontejnerů. Když ti služby často přibývají a ubývají, ušetří to spoustu ruční práce — a když máš tři stabilní kontejnery, je to zbytečná složitost oproti Caddy.
V čem je jiná
Nemá konfigurační soubor pro jednotlivé weby. Sleduje Docker socket a když se objeví kontejner se správnými štítky, začne ho obsluhovat. Když zmizí, přestane.
Cena za to jsou dvě věci: potřebuje přístup k Docker socketu (což je bezpečnostně citlivé) a terminologie je vlastní — entrypoint, router, service, middleware. Než to jednou pochopíš, chvíli to trvá.
Základní nasazení
compose.yml:
services:
traefik:
image: traefik:v3
restart: unless-stopped
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --certificatesresolvers.le.acme.email=ty@example.cz
- --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
networks: [web]
volumes:
letsencrypt:
networks:
web:
exposedbydefault=false je důležité. Bez něj Traefik zveřejní každý kontejner, který uvidí.
Přidání služby
immich:
image: ghcr.io/immich-app/immich-server
networks: [web]
labels:
- traefik.enable=true
- traefik.http.routers.immich.rule=Host(`foto.example.cz`)
- traefik.http.routers.immich.entrypoints=websecure
- traefik.http.routers.immich.tls.certresolver=le
- traefik.http.services.immich.loadbalancer.server.port=2283
Žádné ports, žádný zásah do konfigurace proxy. Kontejner musí být ve stejné síti jako Traefik.
To loadbalancer.server.port je port uvnitř kontejneru. Traefik jde přímo na něj, publikovaný port nepotřebuje. Souvislosti v sítích v Dockeru.
Slovníček Traefiku
| Pojem | Co to je |
|---|---|
| entrypoint | port, na kterém Traefik poslouchá (:80, :443) |
| router | pravidlo, co kam patří (podle Host, cesty, hlavičky) |
| service | cíl, kam se to pošle |
| middleware | úprava po cestě (autentizace, hlavičky, přesměrování) |
| provider | odkud se bere konfigurace (Docker, soubor, Kubernetes) |
Middleware
Autentizace před službou bez vlastního přihlašování:
labels:
- traefik.http.middlewares.auth.basicauth.users=martin:$$2y$$10$$hash
- traefik.http.routers.app.middlewares=auth
V Compose se $ píše jako $$, jinak ho Compose sežere.
Omezení podle IP:
labels:
- traefik.http.middlewares.jenlan.ipallowlist.sourcerange=192.168.1.0/24,10.10.0.0/24
- traefik.http.routers.proxmox.middlewares=jenlan
Bezpečnostní hlavičky:
labels:
- traefik.http.middlewares.sec.headers.stsSeconds=31536000
- traefik.http.middlewares.sec.headers.contentTypeNosniff=true
- traefik.http.middlewares.sec.headers.frameDeny=true
Middleware se dají řetězit oddělené čárkou.
Wildcard certifikát
Přes DNS-01, s tokenem od DNS poskytovatele:
command:
- --certificatesresolvers.le.acme.dnschallenge=true
- --certificatesresolvers.le.acme.dnschallenge.provider=cloudflare
environment:
- CF_DNS_API_TOKEN=${CF_TOKEN}
labels:
- traefik.http.routers.app.tls.domains[0].main=example.cz
- traefik.http.routers.app.tls.domains[0].sans=*.example.cz
Viz certifikáty a Let's Encrypt.
Služby mimo Docker
Pro věci, které v kontejneru neběží (Proxmox, router, NAS), použij souborový provider:
command:
- --providers.file.directory=/etc/traefik/dynamic
volumes:
- ./dynamic:/etc/traefik/dynamic:ro
dynamic/proxmox.yml:
http:
routers:
proxmox:
rule: "Host(`pve.example.cz`)"
entrypoints: [websecure]
service: proxmox
tls:
certresolver: le
services:
proxmox:
loadBalancer:
servers:
- url: "https://192.168.1.5:8006"
serversTransport: skipverify
serversTransports:
skipverify:
insecureSkipVerify: true
To insecureSkipVerify je nutné, protože Proxmox má certifikát podepsaný sám sebou. Čistší, byť pracnější řešení je vystavit mu certifikát z vlastní CA a ověřování nechat zapnuté.
Dashboard
command:
- --api.dashboard=true
labels:
- traefik.http.routers.dash.rule=Host(`traefik.example.cz`)
- traefik.http.routers.dash.service=api@internal
- traefik.http.routers.dash.middlewares=auth,jenlan
Dashboard je užitečný při ladění, ale nikdy ho nevystavuj bez autentizace. Ukazuje kompletní topologii tvých služeb.
Bezpečnostní poznámka k Docker socketu
Přístup k /var/run/docker.sock znamená v praxi root na hostiteli. Kdokoliv, kdo prolomí Traefik, ovládne stroj. Připojení :ro na tom nic nemění, protože socket je API, ne soubor.
Kdo to bere vážně, dá mezi Traefik a socket proxy (tecnativa/docker-socket-proxy), která propustí jen čtení kontejnerů.
Pro homelab je to přijatelné riziko, ale stojí za to o něm vědět. Caddy tenhle problém nemá.
Diagnostika
docker compose logs -f traefik
docker inspect nazev-kontejneru | grep -A20 Labels
| Problém | Příčina |
|---|---|
| Kontejner Traefik nevidí | chybí traefik.enable=true nebo není ve stejné síti |
404 page not found |
pravidlo Host() nesedí, nebo chybí router |
Bad Gateway |
špatný loadbalancer.server.port |
| Certifikát se nevydá | acme.json nemá práva 600, nebo port 80 není dostupný |
Ta práva na acme.json jsou klasika — Traefik odmítne soubor s volnějšími právy použít a v logu to napíše nenápadně.