Caddy Reverse Proxy with Automatic HTTPS for Multiple Apps
Web Infrastructure

Caddy Reverse Proxy with Automatic HTTPS for Multiple Apps

  • Author :Liam K.
  • Date :June 30, 2026
  • Time :17 minutes

Caddy is a modern web server and reverse proxy that provisions and renews TLS certificates automatically. Compared to manual Certbot workflows, Caddy reduces operational overhead while keeping strong defaults for HTTPS redirects, HTTP/2, and optional HTTP/3. This guide walks through a production-ready multi-app setup on Ubuntu or Debian.

Prerequisites

  • Ubuntu 22.04+ or Debian 12 server with a public IP
  • DNS A/AAAA records pointing to the server for each hostname
  • Backend apps listening on localhost (e.g. ports 3000 and 8080)
  • Ports 80 and 443 open in your firewall

Step 1: Install Caddy

bash
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
caddy version

Step 2: Create the Caddyfile

Replace the example domains with your own. Caddy obtains certificates on first request and renews them automatically before expiry.

bash
sudo tee /etc/caddy/Caddyfile >/dev/null <<'EOF'
{
    email admin@example.com
    admin off
}
(common_headers) {
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
[...]
Command truncated. Copy to view full command.

Step 3: Validate and Reload

bash
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl enable caddy
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager

Step 4: Verify TLS and Routing

bash
curl -I https://app.example.com
curl -I https://api.example.com/health
sudo journalctl -u caddy -n 50 --no-pager

Step 5: Enable HTTP/3 (Optional)

HTTP/3 uses QUIC over UDP port 443. Open UDP 443 in your firewall before enabling it.

bash
sudo ufw allow 443/udp
# Add to the global options block in /etc/caddy/Caddyfile:
# {
#     servers {
#         protocols h1 h2 h3
#     }
# }
sudo caddy validate --config /etc/caddy/Caddyfile
[...]
Command truncated. Copy to view full command.

Step 6: Add Basic Rate Limiting

bash
# Install rate limit module if not bundled, then add to a site block:
# rate_limit {
#     zone api_limit {
#         key {remote_host}
#         events 100
#         window 1m
#     }
# }

Production Checklist

  • Keep backend services bound to 127.0.0.1 — only Caddy should be public-facing.
  • Monitor certificate renewal events in journalctl -u caddy.
  • Use separate hostnames per service to isolate blast radius and simplify routing.
  • Test config changes with caddy validate before every reload.
  • Back up /etc/caddy/Caddyfile and document ownership for on-call.

"Automatic HTTPS only saves time when your proxy config is version-controlled, validated, and owned by the same team that runs production."

Technical Author

Technical Author - Liam K.
Liam K.

System administrator and technical writer specializing in server infrastructure, security and deployment. Creating comprehensive guides to help you master server administration.