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
The config for a service:
# /etc/caddy/Caddyfile
cibot.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 terminates HTTPS and 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 such as Puma:
client --HTTPS--> Caddy (:443, TLS) --HTTP--> app (127.0.0.1)
Puma runs the Rack app. Caddy fronts any localhost listener, in Go, Ruby, or another language.
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:
cibot CAA 0 issue "letsencrypt.org"
A subdomain inherits CAA records until a closer record exists. This record overrides the apex policy for that host.