traefik/traefik
Plugins
Plugins extend Traefik with custom middleware (and provider/observability hooks) without recompiling the binary. Two runtimes are supported: Yaegi for Go source, and WebAssembly via Wazero.
Code map
| File | Purpose |
|---|---|
pkg/plugins/manager.go |
Discovery, download, and lifecycle of plugins. |
pkg/plugins/builder.go |
Glue between the plugin manager and the middleware factory. |
pkg/plugins/middlewareyaegi.go |
Yaegi-backed Go middleware. |
pkg/plugins/middlewarewasm.go |
Wazero-backed Wasm middleware. |
pkg/plugins/wasip.go |
WASI host functions exposed to Wasm plugins. |
pkg/plugins/downloader.go |
Module/Artifact download from the plugin registry. |
pkg/plugins/providers.go |
Plugin-provided dynamic providers. |
pkg/plugins/plugins.go |
Plugin manifest types and validation. |
pkg/plugins/types.go |
Manifest field definitions. |
Configuration
Plugins are declared in static configuration under experimental.plugins and experimental.localPlugins:
experimental:
plugins:
rate-limiter-pro:
moduleName: github.com/example/rate-limiter-pro
version: v0.3.1
localPlugins:
custom-headers:
moduleName: github.com/local/custom-headersRemote plugins are downloaded from the Traefik plugin catalog at startup; local plugins are loaded from a directory you control. The manager validates the manifest and links the plugin into the middleware factory.
A user-facing dynamic.Middleware references a plugin by name:
http:
middlewares:
my-rate-limit:
plugin:
rate-limiter-pro:
requestsPerSecond: 10
burst: 20pkg/server/middleware/plugins.go wires the plugin manifest into the middleware chain at apply time.
Yaegi plugins
Yaegi (github.com/traefik/yaegi) is a pure-Go interpreter for Go source. A Yaegi plugin is a Go package that exposes:
package myplugin
type Config struct { /* ... */ }
func CreateConfig() *Config { return &Config{} }
func New(ctx context.Context, next http.Handler, cfg *Config, name string) (http.Handler, error) {
return &myMiddleware{...}, nil
}pkg/plugins/middlewareyaegi.go loads the source files, registers the standard library Yaegi symbols, calls CreateConfig to build a default, and finally New to obtain the http.Handler.
Why Yaegi? It avoids the build complexity of Go plugins (buildmode=plugin) and works cross-platform. Performance is lower than compiled Go but adequate for HTTP middlewares that are not CPU-bound.
Wasm plugins
Wasm plugins are compiled to wasm32-wasi. pkg/plugins/middlewarewasm.go uses Wazero to instantiate them. The host exposes a small surface:
- WASI system calls (file system, clocks, random) via
pkg/plugins/wasip.go. - A Traefik-specific HTTP host module that lets the guest read the request and write the response. The module mirrors the API shape of the Yaegi plugin contract so the same plugin can target both runtimes.
Wasm plugins can be written in any language that targets WASI: Go (TinyGo), Rust, AssemblyScript, etc. They run in a sandbox, so they cannot access the host file system or network unless explicitly granted by the host module.
Plugin manifest
Each plugin ships a .traefik.yml manifest:
displayName: Rate Limiter Pro
type: middleware
runtime: yaegi # or "wasm"
import: github.com/example/rate-limiter-pro
basePkg: ratelimiterpro
testData:
requestsPerSecond: 5pkg/plugins/types.go defines the schema. Fields like runtime, import, basePkg, and testData drive validation and the catalog listing. The manager reads the manifest before loading anything.
Lifecycle
graph TD
StaticConf[static config<br/>experimental.plugins] --> Downloader[downloader.go]
Downloader --> Cache[plugins cache dir]
Cache --> Manager[manager.go]
Manager --> Manifest[load .traefik.yml]
Manifest -->|runtime: yaegi| Yaegi[middlewareyaegi.go]
Manifest -->|runtime: wasm| Wasm[middlewarewasm.go]
Yaegi --> Builder[builder.go]
Wasm --> Builder
Builder --> Factory[pkg/server/middleware/middlewares.go]
Factory -->|attach to chain| Router[pkg/server/router/router.go]When dynamic configuration references a plugin name, the middleware factory looks it up in the plugin manager. Configuration values from dynamic.Middleware.Plugin are passed through as a generic map[string]any to New.
Plugin-provided providers
pkg/plugins/providers.go allows a plugin to act as a dynamic configuration provider, not just a middleware. Plugin providers are wired into the same aggregator as built-in providers, so they participate in the watcher loop with no special handling.
Tests
pkg/plugins/manager_test.go— manifest validation, plugin lifecycle.pkg/plugins/middlewareyaegi_test.go— Yaegi middleware loading and execution.pkg/plugins/middlewarewasm_test.go— Wasm middleware loading.pkg/plugins/downloader_test.go— registry interaction with mocked HTTP.
Limitations and notes
- Yaegi plugins must be self-contained (limited dependency support beyond the standard library).
- Wasm plugins are subject to WASI capabilities. Network or file-system access requires explicit host functions, of which Traefik exposes only what the plugin contract permits.
- Plugin updates require restarting Traefik; hot-reload of plugin code is not supported.
Entry points for modification
- New host function exposed to Wasm plugins: extend
pkg/plugins/wasip.goand update the host module inpkg/plugins/middlewarewasm.go. - New plugin runtime (e.g. native Go plugins): mirror the
middlewareyaegi.go/middlewarewasm.goshape and register inpkg/plugins/manager.go. - New manifest field: add to
pkg/plugins/types.go, validate inpkg/plugins/plugins.go, and document in the plugin catalog.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.