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
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 versionStep 2: Create the Caddyfile
Replace the example domains with your own. Caddy obtains certificates on first request and renews them automatically before expiry.
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"
[...]Step 3: Validate and Reload
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl enable caddy
sudo systemctl reload caddy
sudo systemctl status caddy --no-pagerStep 4: Verify TLS and Routing
curl -I https://app.example.com
curl -I https://api.example.com/health
sudo journalctl -u caddy -n 50 --no-pagerStep 5: Enable HTTP/3 (Optional)
HTTP/3 uses QUIC over UDP port 443. Open UDP 443 in your firewall before enabling it.
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
[...]Step 6: Add Basic Rate Limiting
# 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 validatebefore every reload. - Back up
/etc/caddy/Caddyfileand 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

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