traefik/traefik
Architecture
Traefik is a single Go process. The interesting structure is internal: how a configuration change in your orchestrator becomes a routed request without restarting the binary.
This page walks through the main pieces and how they connect. Subsystem pages under Systems drill into each box.
Bird's-eye view
graph LR
subgraph External["External sources"]
K8s[Kubernetes API]
Docker[Docker / Swarm]
FileSrc[File / KV store]
ACME[Let's Encrypt]
end
subgraph Traefik["Traefik process"]
Providers[Providers<br/>pkg/provider/*]
Aggregator[Provider aggregator<br/>pkg/provider/aggregator]
Watcher[Configuration watcher<br/>pkg/server/configurationwatcher.go]
Factory[Router factory<br/>pkg/server/routerfactory.go]
EPs[Entry points<br/>pkg/server/server_entrypoint_*.go]
Routers[Routers + Middlewares + Services]
end
Client((HTTP/TCP/UDP<br/>client))
Backends((Upstream<br/>services))
K8s --> Providers
Docker --> Providers
FileSrc --> Providers
Providers --> Aggregator
Aggregator -->|dynamic.Message| Watcher
Watcher -->|dynamic.Configurations| Factory
Factory -->|swap handler tree| EPs
Client -->|TCP/UDP/QUIC| EPs
EPs --> Routers
Routers -->|HTTP| Backends
ACME -.->|certificates| RoutersStatic vs dynamic configuration
Traefik distinguishes two kinds of configuration. They live in different packages and have different lifecycles.
| Aspect | Static configuration | Dynamic configuration |
|---|---|---|
| Schema | pkg/config/static/static_config.go |
pkg/config/dynamic/http_config.go, tcp_config.go, udp_config.go, middlewares.go |
| Source | traefik.yml / traefik.toml, CLI flags, env vars |
Providers (Docker, Kubernetes, file watcher, KV stores, REST API, …) |
| When loaded | At startup. Most fields cannot change without a restart. | Continuously. Changes are applied without restarting. |
| Examples | Entry points, providers, certificate resolvers, log/tracing/metrics, API/dashboard | Routers, services, middlewares, TLS certificates, TLS options |
The distinction matters because most of the runtime — including the router tree, certificates, and middleware chains — is rebuilt every time the dynamic config changes.
Process startup
cmd/traefik/traefik.go does the actual wiring. Roughly:
- Build the
static.Configurationfrom the loaders chained intraefik.go(DeprecationLoader,FileLoader,FlagLoader,EnvLoader— all fromgithub.com/traefik/paerser). - Validate it (
SetEffectiveConfiguration+ValidateConfiguration). - Start observability: structured logger via
pkg/observability/logs, metrics registries viapkg/observability/metrics, OpenTelemetry tracing viapkg/observability/tracing. - Construct providers from the static config, wrap them in the aggregator (
pkg/provider/aggregator). - Build a
ConfigurationWatcher(pkg/server/configurationwatcher.go) and register listeners that update the live router tree. - Build TCP/UDP entry points (
pkg/server/server_entrypoint_tcp.go,server_entrypoint_udp.go). - Start the
Server(pkg/server/server.go), which callsStarton entry points and the watcher.
Configuration application loop
The interesting concurrent code is in pkg/server/configurationwatcher.go. It runs three goroutines:
- The provider aggregator pushes
dynamic.Message{ProviderName, Configuration}onto an internal channel. receiveConfigurationsdeduplicates messages per provider, applies registered transformers (middleware plugins, hub, etc.), and pushes the merged snapshot onto another channel.applyConfigurationsreads the latest snapshot and calls each registered listener — typically the router factory, which rebuilds and atomically swaps the entry points' handler trees.
sequenceDiagram
participant P as Provider
participant A as Aggregator
participant W as Watcher
participant F as RouterFactory
participant E as EntryPoint
P->>A: dynamic.Message
A->>W: dynamic.Message
W->>W: deduplicate per provider
W->>W: run transformers
W->>F: dynamic.Configurations (merged)
F->>F: build router tree<br/>(routers + middlewares + services)
F->>E: SwitchRouter(new tree)
Note over E: Subsequent connections use<br/>the new handler tree.The atomic swap is what allows zero-restart configuration changes.
Request lifecycle
Once configuration is applied, an inbound request goes through this chain:
graph TD
Conn[TCP/UDP connection] --> EP[Entry point listener<br/>pkg/server/server_entrypoint_tcp.go]
EP -->|HTTP/HTTPS/HTTP3| Mux[HTTP muxer<br/>pkg/muxer/http]
EP -->|raw TCP| TCPMux[TCP muxer<br/>pkg/muxer/tcp]
EP -->|UDP| UDPHandler[UDP handler<br/>pkg/server/router/udp]
Mux --> Router[matched router]
Router --> Chain[middleware chain<br/>pkg/server/middleware/middlewares.go]
Chain --> Svc[service<br/>pkg/server/service/service.go]
Svc --> LB[load balancer<br/>pkg/server/service/loadbalancer/*]
LB --> RT[smart round-tripper<br/>pkg/proxy/* + pkg/server/service/transport.go]
RT --> Backend[(upstream)]Some details worth knowing:
- The HTTP muxer is implemented in
pkg/muxer/http; it speaks Traefik's rule language (Host(...) && PathPrefix(...)) parsed bypkg/rules/parser.go. - The TCP muxer (
pkg/muxer/tcp) sniffs ALPN and SNI to multiplex TLS, HTTP, and raw TCP on the same port. pkg/proxy/fastis the high-performance HTTP/1.x reverse proxy.pkg/proxy/httputilis the standard-library variant.pkg/proxy/smart_builder.gochooses between them.- TLS certificates and ALPN are handled by
pkg/tls/tlsmanager.go, which also serves ACME-resolved certificates frompkg/provider/acme.
Observability is built in
Logs, metrics, and traces are not bolt-ons. The middleware chain is constructed by pkg/server/middleware/middlewares.go and pkg/server/middleware/observability.go, which automatically wrap user-defined middlewares with:
- An access log middleware (
pkg/middlewares/accesslog). - A capture middleware (
pkg/middlewares/capture) that records latency, status, and byte counts. - A metrics middleware (
pkg/middlewares/metrics) feeding Prometheus, OTLP, Datadog, StatsD, or InfluxDB exporters. - A tracing middleware (
pkg/middlewares/observability) using OpenTelemetry.
See Observability for the runtime wiring.
Dashboard and API
The bundled web UI (webui/, Vue 3 + Vite + TypeScript) is compiled to static assets and embedded into the Go binary via webui/embed.go. The HTTP API that the dashboard consumes is implemented under pkg/api/ — see API.
Entry points for modification
- Adding a new provider: implement
provider.Providerinpkg/provider/<name>and wire it inpkg/config/static/static_config.goandpkg/provider/aggregator/aggregator.go. - Adding a new middleware: implement
http.Handlerfactory inpkg/middlewares/<name>and register it inpkg/server/middleware/middlewares.goplus the dynamic config schema inpkg/config/dynamic/middlewares.go. - Adding a new load-balancing strategy: see
pkg/server/service/loadbalancer/for existing implementations (wrr,p2c,hrw,failover,mirror,leasttime).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.