caddyserver/caddy
Debugging
Caddy is not chatty by default. When something doesn't behave, you usually need to do one of three things: turn up the log level, see exactly what config is running, or attach a profiler.
Crank up logging
Add a logging block to the Caddyfile (or set Config.Logging in JSON):
{
debug
}That sets the default logger to DEBUG. For per-module verbosity:
{
log default {
level DEBUG
}
log accesslog {
include http.log.access
output file /var/log/caddy/access.log
}
}Implementation: logging.go builds the zap logger tree at provision time. Per-module loggers come from caddy.Context.Logger() (context.go), which returns a child logger named after the module's ID — so a debug line about the file server has fields tying it back to http.handlers.file_server.
See the actual JSON
If you suspect the Caddyfile adapter is doing something surprising:
caddy adapt --config Caddyfile --prettyadapt exits without starting any servers. Useful flags:
--validate— also run the provisioning step and abort on errors.--adapter caddyfile(default if config ends inCaddyfile).
Inspect the live config
While Caddy is running:
curl localhost:2019/config/ # full config
curl localhost:2019/config/apps/http/servers/srv0/ # subtree
curl localhost:2019/pki/ca/local # local CA info
curl localhost:2019/reverse_proxy/upstreams # health of upstreams
curl localhost:2019/metrics # PrometheusRoutes are registered in admin.go and by modules implementing caddy.AdminRouter (modules/caddyhttp/reverseproxy/admin.go, modules/caddypki/adminapi.go, modules/metrics/).
Common failure modes
| Symptom | What to check |
|---|---|
loading config: provisioning module 'http': loading http app … |
Look at the chain of nested errors — Caddy reports the full path through the module tree. The leaf error is the real one. |
address … already in use on reload |
Another Caddy is running, or a previous instance didn't release sockets. listen_unix.go uses SO_REUSEPORT to allow graceful handoff but only across the same process group. |
| Reload silently restored the old config | The new config returned an error during Provision/Validate/Start. Caddy's Load runs Cleanup and rolls back without crashing. Check the log; the error will be there even if the CLI looks happy. |
tls: failed to load certificates |
caddytls couldn't reach storage or the issuer. Inspect ~/.local/share/caddy (Linux), ~/Library/Application Support/Caddy (macOS), or %AppData%\Caddy (Windows). |
| ACME challenges fail in tests | Use the dns.providers.mock provider; see caddytest/integration/mockdns_test.go. |
Profiling
The admin endpoint also exposes Go's pprof handlers because admin.go imports net/http/pprof:
curl -o /tmp/cpu.prof "http://localhost:2019/debug/pprof/profile?seconds=30"
go tool pprof /tmp/cpu.profAvailable profiles include goroutine, heap, allocs, mutex, and block.
Getting a stack trace
Send SIGQUIT (Linux/macOS) for a full goroutine dump:
kill -QUIT $(pgrep caddy)sigtrap_posix.go and sigtrap.go install handlers for SIGINT, SIGTERM, and SIGUSR1. SIGUSR1 triggers a graceful reload using the most recent config file.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.