SuperAPI AI Directory

caddy

Deployment & operations

View repository

Updated 10-15 21:49

About this skill

Caddy

Caddy is an enterprise-grade web server written in Go, featuring automatic TLS certificate provisioning by default, modern HTTP/3 support, and concise configuration syntax.

When to Use

  • Automated TLS & Reverse Proxying: Instant HTTPS certificates issued via Let's Encrypt / ZeroSSL with zero manual setup.
  • Modern Microservice Edge Proxy: HTTP/2 and HTTP/3 reverse proxying with clean, human-readable Caddyfiles.
  • Local Development HTTPS: Issuing trusted local root certificates automatically for development environments.
  • Zero-Downtime Hot Reloading: Updating configurations via REST API or caddy reload without dropping connections.

Quick Start

# Caddyfile
example.com {
    reverse_proxy localhost:3000
    encode zstd gzip
    file_server
}

Core Concepts

Production Reverse Proxy Caddyfile with Security Headers

Clean reverse proxy configuration with automatic HTTPS:

# /etc/caddy/Caddyfile
api.example.com {
    # Automatic TLS enabled by default!

    # Reverse proxy to backend application cluster
    reverse_proxy 127.0.0.1:8080 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-Proto {scheme}

        # Health checks and failover
        lb_policy round_robin
        health_path /healthz
        health_interval 10s
    }

    # Security headers
    header {
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        -Server # Remove server fingerprint header
    }

    # Structured JSON access logging
    log {
        output file /var/log/caddy/access.log {
            roll_size 50mb
            roll_keep 10
        }
        format json
    }
}

Static File Server with Gzip & Zstandard Compression

Serving high-performance frontends with fallback for Single Page Apps (SPAs):

app.example.com {
    root * /var/www/app/dist
    encode zstd gzip

    # SPA routing: try file, then fallback to index.html
    try_files {path} /index.html
    file_server
}

Live Configuration Updates via Admin API

Modifying configuration dynamically without server restarts:

# Validate Caddyfile syntax
caddy validate --config /etc/caddy/Caddyfile

# Zero-downtime configuration reload
caddy reload --config /etc/caddy/Caddyfile

# Query current running config via Admin API
curl http://localhost:2019/config/ | jq .

Common Patterns

Reverse Proxy with Automated Let's Encrypt and Security Headers

Problem: Tedious manual SSL certificate provisioning, renewal cron jobs, and complex Nginx configs.

Solution: Use Caddy's declarative Caddyfile:

api.example.com {
    # Automatic HTTPS via Let's Encrypt / ZeroSSL

    # Security headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }

    # Reverse proxy to internal microservice
    reverse_proxy 127.0.0.1:8080 {
        health_uri /health
        health_interval 10s
    }
}

Best Practices

Do:

  • Use encode zstd gzip on static routes to reduce bandwidth and speed up client loading.
  • Use try_files {path} /index.html for client-side Single Page Application (SPA) routing.
  • Test configuration files with caddy validate before reloading in production pipelines.
  • Configure structured JSON logging with automated log rolling.

Don't:

  • Expose Caddy's internal Admin API port (2019) to public network interfaces.
  • Use Caddy without persistent storage volumes for /data in containers; certificates will be re-requested on restart.
  • Disable automatic HTTPS (http://) unless strictly operating behind an external cloud load balancer.

Troubleshooting

Error Cause Solution
certificate obtained error: acme: error: 400 Domain DNS A/AAAA record does not point to Caddy server IP. Verify DNS propagation and ensure ports 80 and 443 are reachable.
caddy.service: Failed with result 'exit-code' Syntax error in /etc/caddy/Caddyfile. Run caddy validate --config /etc/caddy/Caddyfile to identify syntax errors.
502 Bad Gateway Upstream service port down or listening on localhost only inside container. Verify upstream service is active: curl http://127.0.0.1:8080.

References