Tools: Caddy Has a Free API — HTTPS Web Server with Automatic TLS Certificates

Tools: Caddy Has a Free API — HTTPS Web Server with Automatic TLS Certificates

Why Caddy?

Quick Start

Caddyfile (The Simplest Config)

Reverse Proxy with Load Balancing

Headers, CORS, Compression

Admin API (Runtime Config)

Rate Limiting

Docker Compose Caddy is a web server that automatically provisions and renews HTTPS certificates. No certbot, no nginx config files, no manual renewal — just works. That's it. Caddy automatically gets TLS certs for all three domains. Deploying scraping infrastructure? Check out my Apify actors for managed web scraping, or email [email protected] for custom deployment solutions. Caddy, Nginx, or Traefik — which web server do you use? Share below! 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

# Install -weight: 500;">brew -weight: 500;">install caddy # macOS -weight: 500;">apt -weight: 500;">install caddy # Ubuntu # Serve current directory caddy file-server --browse # Reverse proxy caddy reverse-proxy --to localhost:3000 # Install -weight: 500;">brew -weight: 500;">install caddy # macOS -weight: 500;">apt -weight: 500;">install caddy # Ubuntu # Serve current directory caddy file-server --browse # Reverse proxy caddy reverse-proxy --to localhost:3000 # Install -weight: 500;">brew -weight: 500;">install caddy # macOS -weight: 500;">apt -weight: 500;">install caddy # Ubuntu # Serve current directory caddy file-server --browse # Reverse proxy caddy reverse-proxy --to localhost:3000 # Serve static site with HTTPS mysite.com { root * /var/www/mysite file_server } # Reverse proxy api.mysite.com { reverse_proxy localhost:3000 } # SPA with fallback app.mysite.com { root * /var/www/app try_files {path} /index.html file_server } # Serve static site with HTTPS mysite.com { root * /var/www/mysite file_server } # Reverse proxy api.mysite.com { reverse_proxy localhost:3000 } # SPA with fallback app.mysite.com { root * /var/www/app try_files {path} /index.html file_server } # Serve static site with HTTPS mysite.com { root * /var/www/mysite file_server } # Reverse proxy api.mysite.com { reverse_proxy localhost:3000 } # SPA with fallback app.mysite.com { root * /var/www/app try_files {path} /index.html file_server } myapp.com { reverse_proxy { to localhost:3001 to localhost:3002 to localhost:3003 lb_policy round_robin health_uri /health health_interval 10s } } myapp.com { reverse_proxy { to localhost:3001 to localhost:3002 to localhost:3003 lb_policy round_robin health_uri /health health_interval 10s } } myapp.com { reverse_proxy { to localhost:3001 to localhost:3002 to localhost:3003 lb_policy round_robin health_uri /health health_interval 10s } } api.mysite.com { header { Access-Control-Allow-Origin * Access-Control-Allow-Methods "GET, POST, PUT, DELETE" X-Frame-Options DENY -Server # Remove server header } encode gzip zstd reverse_proxy localhost:3000 } api.mysite.com { header { Access-Control-Allow-Origin * Access-Control-Allow-Methods "GET, POST, PUT, DELETE" X-Frame-Options DENY -Server # Remove server header } encode gzip zstd reverse_proxy localhost:3000 } api.mysite.com { header { Access-Control-Allow-Origin * Access-Control-Allow-Methods "GET, POST, PUT, DELETE" X-Frame-Options DENY -Server # Remove server header } encode gzip zstd reverse_proxy localhost:3000 } # Get current config -weight: 500;">curl localhost:2019/config/ # Add a new site at runtime -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["new.mysite.com"]}], "handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:4000"}]}] }' # Load entire config -weight: 500;">curl -X POST localhost:2019/load \ -H 'Content-Type: application/json' \ -d @caddy.json # Get current config -weight: 500;">curl localhost:2019/config/ # Add a new site at runtime -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["new.mysite.com"]}], "handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:4000"}]}] }' # Load entire config -weight: 500;">curl -X POST localhost:2019/load \ -H 'Content-Type: application/json' \ -d @caddy.json # Get current config -weight: 500;">curl localhost:2019/config/ # Add a new site at runtime -weight: 500;">curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \ -H 'Content-Type: application/json' \ -d '{ "match": [{"host": ["new.mysite.com"]}], "handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:4000"}]}] }' # Load entire config -weight: 500;">curl -X POST localhost:2019/load \ -H 'Content-Type: application/json' \ -d @caddy.json api.mysite.com { rate_limit { zone api { key {remote_host} events 100 window 1m } } reverse_proxy localhost:3000 } api.mysite.com { rate_limit { zone api { key {remote_host} events 100 window 1m } } reverse_proxy localhost:3000 } api.mysite.com { rate_limit { zone api { key {remote_host} events 100 window 1m } } reverse_proxy localhost:3000 } services: caddy: image: caddy:latest ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - caddy_config:/config app: build: . expose: - "3000" volumes: caddy_data: caddy_config: services: caddy: image: caddy:latest ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - caddy_config:/config app: build: . expose: - "3000" volumes: caddy_data: caddy_config: services: caddy: image: caddy:latest ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - caddy_config:/config app: build: . expose: - "3000" volumes: caddy_data: caddy_config: - Automatic HTTPS — provisions TLS certificates from Let's Encrypt automatically - Zero config — a 3-line Caddyfile replaces 50 lines of nginx config - HTTP/3 — supported out of the box - API-first — configure everything via JSON API at runtime