DEV Community

Alex Spinov
Alex Spinov

Posted on

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

Caddy is a web server that automatically provisions and renews HTTPS certificates. No certbot, no nginx config files, no manual renewal — just works.

Why Caddy?

  • 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

Quick Start

# Install
brew install caddy  # macOS
apt install caddy   # Ubuntu

# Serve current directory
caddy file-server --browse

# Reverse proxy
caddy reverse-proxy --to localhost:3000
Enter fullscreen mode Exit fullscreen mode

Caddyfile (The Simplest Config)

# 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
}
Enter fullscreen mode Exit fullscreen mode

That's it. Caddy automatically gets TLS certs for all three domains.

Reverse Proxy with Load Balancing

myapp.com {
    reverse_proxy {
        to localhost:3001
        to localhost:3002
        to localhost:3003
        lb_policy round_robin
        health_uri /health
        health_interval 10s
    }
}
Enter fullscreen mode Exit fullscreen mode

Headers, CORS, Compression

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
}
Enter fullscreen mode Exit fullscreen mode

Admin API (Runtime Config)

# Get current config
curl localhost:2019/config/

# Add a new site at runtime
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
curl -X POST localhost:2019/load \
  -H 'Content-Type: application/json' \
  -d @caddy.json
Enter fullscreen mode Exit fullscreen mode

Rate Limiting

api.mysite.com {
    rate_limit {
        zone api {
            key {remote_host}
            events 100
            window 1m
        }
    }
    reverse_proxy localhost:3000
}
Enter fullscreen mode Exit fullscreen mode

Docker Compose

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:
Enter fullscreen mode Exit fullscreen mode

Deploying scraping infrastructure? Check out my Apify actors for managed web scraping, or email spinov001@gmail.com for custom deployment solutions.

Caddy, Nginx, or Traefik — which web server do you use? Share below!

Top comments (0)