Why choose Caddy as the front end on your VPS?
The historical complexity of a reverse proxy comes down to TLS: generating a certificate, configuring renewal, managing the HTTP→HTTPS redirection. Caddy removes all of that. As soon as you specify a domain name in the Caddyfile, it contacts Let's Encrypt (or ZeroSSL as a fallback), provisions the certificate, staples it (OCSP stapling) and renews it in the background. The configuration is readable, short, and hot-reloadable without service interruption.
Caddy's strengths in production
- End-to-end automatic HTTPS: issuance, renewal and redirection without intervention
- Minimalist Caddyfile: a block of a few lines per site, far shorter than an Nginx config
- Built-in reverse proxy with health checks and load balancing to your containers or local ports
- HTTP/2 and HTTP/3 (QUIC) enabled by default
- Hot reload of the configuration (
caddy reload) without interrupting connections - JSON administration API to drive the configuration dynamically
Prerequisites
Caddy is frugal: 1 vCPU and 512 MB to 1 GB of RAM are enough to serve several sites as a reverse proxy. You can choose between installing it as a system binary (systemd service) on Ubuntu/Debian, or running it in a Docker container. In both cases, you need a domain pointing to the VPS IP and ports 80, 443 (and 443/UDP for HTTP/3) open in your firewall.
Deploy Caddy as a reverse proxy
Install Caddy
On Ubuntu/Debian, add the official repository then
apt install caddy. Caddy registers itself as a systemd service active at startup. Check:systemctl status caddy. In container mode, start from thecaddy:latestimage and mount a volume on/datato persist the certificates.Point the DNS and open the ports
Create an A record
app.yourdomain.comto the VPS IP. Open the necessary ports:ufw allow 80,ufw allow 443andufw allow 443/udpfor HTTP/3. Port 80 is essential for Let's Encrypt's HTTP challenge.Write the Caddyfile
Edit
/etc/caddy/Caddyfile. To expose an application running locally on port 3000:app.yourdomain.com { reverse_proxy localhost:3000 }. That's all: Caddy deduces that HTTPS is needed because you specified a domain and triggers the certificate issuance.Reload and check
Apply the configuration without downtime:
caddy reload --config /etc/caddy/Caddyfile. Follow the certificate acquisition in the logs:journalctl -u caddy -f. On the first HTTPS call to your domain, the certificate is in place.Add security headers and compression
Enrich the block with a
headerdirective for HSTS and the anti-clickjacking headers, and enableencode gzip zstdfor compression. Since the config is declarative, these additions stay readable and a simplecaddy reloadapplies them.Logging in for the first time
Caddy is a web server; it has no login interface. After installation it serves its welcome page on port 80, and you configure it over SSH by editing /etc/caddy/Caddyfile then running systemctl reload caddy. Automatic TLS will only be enabled once a real domain name is declared in that file.
To host several applications on the same VPS, simply list several site blocks in the same Caddyfile, each with its reverse_proxy. And for local development without a public domain, replace the domain name with :80 or use the tls internal directive: Caddy then generates a local CA and signs the certificate itself, handy for an internal pre-production environment.
The official documentation
For advanced configuration and options specific to the tool, refer to the official Caddy documentation. This guide covers going live on a VPS; the vendor's docs remain the reference for fine-tuning, major updates and specific use cases.