caddyserver/caddy
Admin API
Caddy's running configuration is mutable at runtime through a built-in HTTP API. Default address localhost:2019. Defined in admin.go (~49 KB).
Purpose
Let operators (and other tools) read and replace the running config without restarting Caddy. The same API also exposes module-defined endpoints for inspection: PKI metadata, reverse-proxy upstream health, Prometheus metrics, and pprof handlers.
Directory layout
| Path | Role |
|---|---|
admin.go |
AdminConfig, AdminRouter interface, route registration, /load and /config handlers, origin enforcement |
caddy.go: Load |
The function /load ultimately calls |
modules/caddyhttp/reverseproxy/admin.go |
Reverse-proxy upstream introspection routes |
modules/caddypki/adminapi.go |
/pki/ endpoints |
modules/metrics/ |
/metrics Prometheus exposition |
Key abstractions
| Type | Where | Description |
|---|---|---|
AdminConfig |
admin.go |
Top-level config: listen address, origin enforcement, identity (mTLS), remote control |
AdminRoute |
admin.go |
{Pattern, Handler} registered by module-supplied admin endpoints |
AdminRouter |
admin.go |
Module interface — Routes() []AdminRoute |
adminHandler |
admin.go |
Wraps http.ServeMux and applies CORS / origin checks |
AdminHandler / AdminHandlerFunc |
admin.go |
The handler shape with error returns |
How it works
graph TD
Curl[curl localhost:2019/load] --> Admin
AdminRouterModule[modules implementing AdminRouter] -->|register at provision| Admin
Admin -->|dispatch| BuiltIn[/load, /config, /id, /reverse_proxy/upstreams]
Admin -->|dispatch| Module[/pki/, /metrics]
Admin -->|enforce| Origin[Origin/Host check]
BuiltIn -->|JSON in| Loader[caddy.Load]
Loader --> NewConfig[New Config]
NewConfig -->|provision/start| Apps
Loader -->|on failure| RollbackOrigin enforcement
By default the admin endpoint listens on localhost:2019 and rejects requests whose Host or Origin headers don't match the listen address. This is in admin.go's originAllowed checks. Configure with AdminConfig.EnforceOrigin and AdminConfig.Origins. When the listener binds to a non-loopback address, you should also enable client-cert authentication via AdminConfig.Identity.
Built-in routes
| Path | Method | Purpose |
|---|---|---|
/load |
POST | Replace the entire running config |
/config/[path...] |
GET, POST, PUT, PATCH, DELETE | Read or surgically edit subtrees of the running config |
/id/<id> |
GET, PUT, DELETE | Operate on objects by @id (Caddy supports @id keys for stable refs) |
/stop |
POST | Stop the server gracefully |
/adapt |
POST | Run a config adapter, return JSON without applying it |
The /config/ family lets you do partial updates without uploading a full document — PUT /config/apps/http/servers/srv0/routes/0 swaps a single route in place.
Module-supplied routes
A module exposes admin endpoints by implementing caddy.AdminRouter:
func (m *MyModule) Routes() []caddy.AdminRoute {
return []caddy.AdminRoute{{
Pattern: "/myfeature/",
Handler: caddy.AdminHandlerFunc(m.handle),
}}
}During admin server provisioning (admin.go), every module that implements AdminRouter is collected and its routes are added to the mux. Each route's pattern is namespaced — Pattern: "/pki/" becomes localhost:2019/pki/....
Examples in the standard build:
modules/caddyhttp/reverseproxy/admin.goregisters/reverse_proxy/upstreams(lists upstreams + health).modules/caddypki/adminapi.goregisters/pki/ca/<id>and certificate-listing routes.modules/metrics/registers/metrics(Prometheus).
net/http/pprof is also imported so /debug/pprof/... is exposed when the admin endpoint is up.
/load semantics
POST /load runs the body through caddy.Load:
- Hash the new JSON; if it equals the current hash and
Cache-Control: must-revalidateisn't set, skip. - Parse into
Config, run module provisioning, then appStarts in order. - On any failure, run
Cleanupand roll back to the prior running config. - On success, swap the current config under a mutex; emit a structured log line and notify the OS service manager via
notify.
Origin enforcement, throttling (one in-flight load at a time), and load-deadline handling all live in admin.go.
Integration points
- CLI:
caddy reload,caddy adapt --validate, andcaddy stopall call the admin API rather than implementing the operations again. - Modules: any module implementing
AdminRouterextends the API surface. - Identity:
AdminConfig.Identityis a managed cert configured for the admin endpoint itself, used when binding to a public address.
Entry points for modification
- Add a built-in route? Edit
admin.gonear the existing/load//confighandlers. - Add origin/auth checks?
originAllowedand the surrounding middleware setup. - Add a module-supplied endpoint? Implement
AdminRouteron your module — no edits to the core needed.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.