Tools: Caddy Has a Free API You've Never Heard Of (2026)

Tools: Caddy Has a Free API You've Never Heard Of (2026)

What Makes Caddy Special?

The Hidden API: Dynamic Configuration

PKI API — Certificate Management

Caddyfile — The Simple API

Quick Start

Why DevOps Choose Caddy Caddy is a web server with automatic HTTPS. Unlike Nginx, it handles TLS certificates automatically and has a powerful REST API for dynamic configuration — no restarts needed. Caddy exposes a full REST API for live configuration: A DevOps engineer shared: "We replaced our Nginx + certbot + cron setup (5 config files, a renewal script, and monthly cert failures) with a 12-line Caddyfile. Zero cert issues in 2 years. The admin API lets us add backends dynamically during blue-green deploys." Need infrastructure automation? Email [email protected] or check my tools. Nginx or Caddy? What's your web server of choice? Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

# Get current config -weight: 500;">curl localhost:2019/config/ | jq . # Add a new site dynamically — no -weight: 500;">restart! -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["api.example.com"]}], "handle": [{ "handler": "reverse_proxy", "upstreams": [{"dial": "localhost:3000"}] }] }' # Update upstream without downtime -weight: 500;">curl -X PATCH localhost:2019/config/apps/http/servers/srv0/routes/0/handle/0/upstreams \ -H 'Content-Type: application/json' \ -d '[{"dial": "localhost:3001"}, {"dial": "localhost:3002"}]' # Delete a route -weight: 500;">curl -X DELETE localhost:2019/config/apps/http/servers/srv0/routes/0 # Get current config -weight: 500;">curl localhost:2019/config/ | jq . # Add a new site dynamically — no -weight: 500;">restart! -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["api.example.com"]}], "handle": [{ "handler": "reverse_proxy", "upstreams": [{"dial": "localhost:3000"}] }] }' # Update upstream without downtime -weight: 500;">curl -X PATCH localhost:2019/config/apps/http/servers/srv0/routes/0/handle/0/upstreams \ -H 'Content-Type: application/json' \ -d '[{"dial": "localhost:3001"}, {"dial": "localhost:3002"}]' # Delete a route -weight: 500;">curl -X DELETE localhost:2019/config/apps/http/servers/srv0/routes/0 # Get current config -weight: 500;">curl localhost:2019/config/ | jq . # Add a new site dynamically — no -weight: 500;">restart! -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["api.example.com"]}], "handle": [{ "handler": "reverse_proxy", "upstreams": [{"dial": "localhost:3000"}] }] }' # Update upstream without downtime -weight: 500;">curl -X PATCH localhost:2019/config/apps/http/servers/srv0/routes/0/handle/0/upstreams \ -H 'Content-Type: application/json' \ -d '[{"dial": "localhost:3001"}, {"dial": "localhost:3002"}]' # Delete a route -weight: 500;">curl -X DELETE localhost:2019/config/apps/http/servers/srv0/routes/0 # Issue certificates on demand -weight: 500;">curl -X POST localhost:2019/pki/ca/local/certificates \ -H 'Content-Type: application/json' \ -d '{"subject": {"common_name": "internal.dev"}}' # List managed certificates -weight: 500;">curl localhost:2019/pki/ca/local/certificates | jq . # Issue certificates on demand -weight: 500;">curl -X POST localhost:2019/pki/ca/local/certificates \ -H 'Content-Type: application/json' \ -d '{"subject": {"common_name": "internal.dev"}}' # List managed certificates -weight: 500;">curl localhost:2019/pki/ca/local/certificates | jq . # Issue certificates on demand -weight: 500;">curl -X POST localhost:2019/pki/ca/local/certificates \ -H 'Content-Type: application/json' \ -d '{"subject": {"common_name": "internal.dev"}}' # List managed certificates -weight: 500;">curl localhost:2019/pki/ca/local/certificates | jq . # Caddyfile — entire config in ~10 lines api.example.com { reverse_proxy localhost:3000 encode gzip log { output file /var/log/caddy/api.log } } app.example.com { root * /var/www/app file_server try_files {path} /index.html } *.example.com { tls { dns cloudflare {env.CF_TOKEN} } respond "Wildcard works!" } # Caddyfile — entire config in ~10 lines api.example.com { reverse_proxy localhost:3000 encode gzip log { output file /var/log/caddy/api.log } } app.example.com { root * /var/www/app file_server try_files {path} /index.html } *.example.com { tls { dns cloudflare {env.CF_TOKEN} } respond "Wildcard works!" } # Caddyfile — entire config in ~10 lines api.example.com { reverse_proxy localhost:3000 encode gzip log { output file /var/log/caddy/api.log } } app.example.com { root * /var/www/app file_server try_files {path} /index.html } *.example.com { tls { dns cloudflare {env.CF_TOKEN} } respond "Wildcard works!" } -weight: 500;">brew -weight: 500;">install caddy caddy reverse-proxy --from :443 --to :3000 # That's it — HTTPS is automatic -weight: 500;">brew -weight: 500;">install caddy caddy reverse-proxy --from :443 --to :3000 # That's it — HTTPS is automatic -weight: 500;">brew -weight: 500;">install caddy caddy reverse-proxy --from :443 --to :3000 # That's it — HTTPS is automatic - Automatic HTTPS — Let's Encrypt certificates out of the box - REST API — modify configuration without restarts - Caddyfile — human-readable config format - Zero-downtime config — hot-reload via API - Single binary — no dependencies