Caddy — Reference
Links
- Website: https://caddyserver.com
- Docs: https://caddyserver.com/docs
- API docs: https://caddyserver.com/docs/api
- Caddyfile directives: https://caddyserver.com/docs/caddyfile/directives
- reverse_proxy directive: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy
- GitHub: https://github.com/caddyserver/caddy
Admin API
Caddy exposes an admin API on localhost:2019 (LXC 105 only — not exposed externally). All requests are unauthenticated since the API is localhost-only.
Get current config (JSON)
ssh [email protected] "curl -s localhost:2019/config/" | python3 -m json.tool
Get specific config section
# List all server routes
ssh [email protected] "curl -s localhost:2019/config/apps/http/servers/"
Load a new config
ssh [email protected] "curl -s -X POST localhost:2019/load \
-H 'Content-Type: text/caddyfile' \
--data-binary @/etc/caddy/Caddyfile"
Check reverse proxy upstream health
ssh [email protected] "curl -s localhost:2019/reverse_proxy/upstreams" | python3 -c \
"import json,sys; [print(f'{u[\"address\"]} healthy={u[\"healthy\"]} requests={u[\"num_requests\"]}') for u in json.load(sys.stdin)]"
Stop Caddy gracefully
ssh [email protected] "curl -s -X POST localhost:2019/stop"
CLI
Run from LXC 105 (ssh [email protected]).
# Reload config (zero-downtime)
caddy reload --config /etc/caddy/Caddyfile
# Validate config without applying
caddy validate --config /etc/caddy/Caddyfile
# Format Caddyfile (standardize indentation)
caddy fmt --overwrite /etc/caddy/Caddyfile
# Convert Caddyfile to JSON (useful for API debugging)
caddy adapt --config /etc/caddy/Caddyfile --pretty
# List loaded modules
caddy list-modules
# Version
caddy version
Caddyfile — Common Patterns
Basic reverse proxy
service.eva-00.network {
reverse_proxy 192.168.1.xxx:PORT
}
With WebSocket support (automatic — no extra config needed)
Caddy automatically proxies WebSocket connections.
With custom headers
service.eva-00.network {
reverse_proxy 192.168.1.xxx:PORT {
header_up X-Custom-Header "value"
}
}
Multiple upstreams (load balancing)
service.eva-00.network {
reverse_proxy 192.168.1.10:8080 192.168.1.11:8080 {
lb_policy round_robin
}
}
What the API/CLI Cannot Do
| Gap | Workaround |
|---|---|
| Admin API only accessible from localhost (LXC 105) | SSH into LXC 105 first, then curl |
| No built-in dashboard or status page | Check upstream health via /reverse_proxy/upstreams API or Loki logs |
| Cannot add routes dynamically via API without full JSON config | Use caddy reload with Caddyfile — the IaC workflow handles this |
| No Prometheus metrics endpoint in this deployment | Monitor via Loki log queries; Caddy does support metrics via a module but it's not enabled |
| TLS cert issues are silent until a request fails | Check {job="caddy", unit="caddy.service"} \| json \| msg=~".*tls.*" in Loki |
| Cannot revoke/force-renew a cert via API | Delete cert files in /var/lib/caddy/.local/share/caddy/certificates/ and reload |