DEV Community

Cover image for How to Install Caddy on Ubuntu 24.04: Production Reverse Proxy
Jakson Tate
Jakson Tate

Posted on • Originally published at servermo.com

How to Install Caddy on Ubuntu 24.04: Production Reverse Proxy

Ditch Nginx complexity. Master the official Cloudsmith repository, unlock HTTP/3 with UFW, and build zero-downtime reverse proxies on ServerMO Bare Metal.


Phase 1: Escaping the Ubuntu APT Trap

For years, Nginx has been the undisputed king of web servers. However, managing Nginx requires manually configuring certbot for Let's Encrypt SSL, writing verbose server blocks, and battling complex WebSocket upgrade headers. Caddy changes everything. Written in Go, Caddy secures your sites with Automatic HTTPS by default and routes traffic using a minimal, human-readable Caddyfile.

⚠️ SRE INSTALLATION WARNING: The Default Repo Trap

Many amateur tutorials instruct you to simply run sudo apt install caddy on Ubuntu 24.04. This is a massive mistake. The default Ubuntu repository often hosts severely outdated versions of Caddy that lack critical HTTP/3 performance optimizations and zero-day security patches. You must add the official Cloudsmith Debian Repository to ensure production-grade stability.

# 1. Install prerequisites for adding external repositories
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

# 2. Add the official Caddy GPG signing key
curl -1sLf '[https://dl.cloudsmith.io/public/caddy/stable/gpg.key](https://dl.cloudsmith.io/public/caddy/stable/gpg.key)' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

# 3. Add the official Caddy Cloudsmith repository to your sources list
curl -1sLf '[https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt](https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt)' | sudo tee /etc/apt/sources.list.d/caddy-stable.list

# 4. Update the package index and install the latest Caddy version
sudo apt update
sudo apt install caddy -y

# 5. Verify the installation (Ensure it displays v2.8+ or higher)
caddy version
Enter fullscreen mode Exit fullscreen mode

Phase 2: The HTTP/3 UFW Configuration

Caddy manages its own HTTPS certificates via the ACME protocol. If your firewall is not configured precisely, the entire system will fail.

💡 SRE HIDDEN GEM: Unlocking HTTP/3 (QUIC) & Protecting Port 80

Most basic tutorials tell you to only open TCP 443. Never block Port 80! Port 80 is strictly required for the ACME HTTP-01 challenge to renew Let's Encrypt certificates. Furthermore, Caddy supports HTTP/3 natively, which uses the QUIC protocol over UDP 443. To achieve lightning-fast, multiplexed streaming, you must explicitly open UDP 443 in your firewall.

# Allow Port 80 (Required for Let's Encrypt HTTP Challenge and redirects)
sudo ufw allow 80/tcp

# Allow Port 443 TCP (Standard HTTPS)
sudo ufw allow 443/tcp

# Allow Port 443 UDP (SRE Secret: Required for HTTP/3 QUIC performance)
sudo ufw allow 443/udp

# Reload the firewall to apply changes
sudo ufw reload
Enter fullscreen mode Exit fullscreen mode

Phase 3: Architecting the Reverse Proxy

If you are running a Node.js, Python, or Docker application locally (e.g., on Port 8080), you should never expose that port directly to the internet. Caddy acts as a Reverse Proxy, intercepting traffic, encrypting it with HTTPS, and passing it securely to your local application.

⚠️ SRE WARNING: The Nginx X-Forwarded-For Anti-Pattern

In Nginx, developers are forced to manually configure X-Forwarded-For headers so the backend application can see the user's real IP address. Many mistakenly copy this behavior into their Caddyfile. Do not do this. Caddy automatically sets X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host natively. Manually adding these headers in Caddy is an anti-pattern that can double-append headers and break your application logic.

Edit the configuration file (/etc/caddy/Caddyfile):

# Replace with your actual domain name pointing to your server's IP
api.yourdomain.com {

    # Enable Zstandard and Gzip compression for faster payload delivery
    encode zstd gzip

    # The SRE Reverse Proxy Block (No manual IP headers needed!)
    reverse_proxy 127.0.0.1:8080

    # Optional: Apply Enterprise Security Headers (Avoiding the HSTS preload trap)
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }
}
Enter fullscreen mode Exit fullscreen mode

Note on WebSockets: Unlike Nginx, which requires complex Connection Upgrade directives, Caddy natively detects and proxies WebSocket connections automatically without any additional configuration!


Phase 4: Zero-Downtime SRE Reloads

Once your Caddyfile is written, you must apply the changes. Never use sudo systemctl restart caddy in a production environment. A restart kills the process, instantly dropping all active user connections and causing application downtime.

Instead, use Caddy's built-in formatting and zero-downtime reload capabilities:

# 1. Format the Caddyfile beautifully
sudo caddy fmt --overwrite /etc/caddy/Caddyfile

# 2. Validate the configuration syntax before applying
sudo caddy validate --config /etc/caddy/Caddyfile

# 3. Perform a zero-downtime graceful reload
sudo systemctl reload caddy

# 4. Monitor logs to ensure Let's Encrypt successfully provisioned SSL
sudo journalctl -u caddy -f
Enter fullscreen mode Exit fullscreen mode

Phase 5: The ServerMO Bare Metal Advantage

Caddy is an incredibly powerful web server, but because it runs on the Go runtime (which utilizes a Garbage Collector), it can consume slightly more memory under massive concurrent loads compared to Nginx. If you are deploying an API Gateway handling tens of thousands of HTTP/3 streams, running it on a shared Cloud VM will introduce "noisy neighbor" latency.

To unlock the absolute peak performance of Caddy, deploy it directly on ServerMO Dedicated Bare Metal Servers. Our infrastructure provides dedicated AMD EPYC CPU cores, meaning Caddy never fights for compute cycles during aggressive SSL handshakes. Combined with our 10Gbps to 25Gbps Unmetered Networks, you can push Caddy's HTTP/3 streaming to the absolute limit without ever worrying about cloud bandwidth throttling or exorbitant egress taxes.


💬 Caddy Web Server FAQ

Does Caddy replace Nginx for Reverse Proxy performance?

Yes. While Nginx has a slight edge in raw static file throughput, Caddy offers superior operational efficiency. Caddy handles automatic HTTPS, native HTTP/3 (QUIC) streaming, and WebSocket upgrades out-of-the-box without the verbose configuration required by Nginx.

What ports does Caddy need open on Ubuntu UFW?

Caddy requires three specific ports: TCP 80 for ACME HTTP-01 certificate challenges, TCP 443 for standard HTTPS traffic, and UDP 443 to enable high-speed HTTP/3 streaming connections.

How do I pass the real client IP through a Caddy Reverse Proxy?

Unlike Nginx, you do not need to configure anything. Caddy automatically passes the real client IP via the X-Forwarded-For header by default. Manually setting this in your Caddyfile is an anti-pattern and can duplicate headers.

Why did my Caddy Let's Encrypt certificate fail to provision?

Certificate failures usually occur for two reasons: either your domain's DNS A record hasn't fully propagated to your server's IP, or your server's firewall is blocking Port 80, which Let's Encrypt requires to validate domain ownership.


Read the full tutorial on ServerMO:

How to Install Caddy on Ubuntu 24.04: Production Reverse Proxy | ServerMO

Top comments (0)