web / caddy

When I run a web service on a VM, I use Caddy as a reverse proxy to terminate TLS in front of the app.

Config

# /etc/caddy/Caddyfile
sockeye.example.com {
  reverse_proxy 127.0.0.1:1994
}

Point DNS at the box and reload:

sudo cp Caddyfile /etc/caddy/Caddyfile
sudo systemctl reload caddy

The app listens on localhost. Caddy renews a Let's Encrypt certificate.

Compared to a PaaS

A PaaS like Render provisions certificates and terminates HTTPS at a shared edge with DDoS protection. Caddy gives me the same certificates on a VM. I lose the edge and gain control and a flat cost.

Caddy vs nginx

Both are fast enough at my scale. Caddy renews certificates by default. nginx needs certbot and a renewal timer. Caddy is a single Go binary, like everything else I deploy.

Caddy vs an app server

Caddy runs in front of an application server:

client --HTTPS--> Caddy (:443, TLS) --HTTP--> app (127.0.0.1)

Caddy fronts any localhost listener: a Go binary, or an app server such as Puma for a Ruby app.

CAA records

If certificate issuance fails, check the domain's CAA records. They restrict which authorities can issue certificates. If the apex excludes Let's Encrypt, add a record for the subdomain:

sockeye  CAA  0 issue "letsencrypt.org"

A subdomain inherits CAA records until a closer record exists. This record overrides the apex policy for that host.

← All articles