So, it’s 2021, Devember is starting and all the things should have https and you want to save time and not deal with certificate management stuff.
… or maybe you think you have a pretty nifty setup and don’t realize you have a problem (like I did, I’ll describe).
Caddy is a one stop shop for http serving, http proxy-ing, and https certificate renewal.
Nifty before setup
I’d given up on certbot pretty early because I don’t like stopping http servers to update certs and giving the machine control over DNS.
I used acme.sh with webroot authentication.
Essentially this is a shell script that does cert renewals for you. The webroot auth works like this:
- you (acme.sh) generates a CSR, calls the Let’s Encrypt or ZeroSSL ACME APIs that return a challenge
- challenge is saved into the filesystem, such that it can be retrieved via plaintext
http://www.yourdomain.com/.well-known/acme-challenge/1234.txt
- Let’s Encrypt/ZeroSSL fetch it and to them this proves that you have control over
www.yourdomain.com
so they return to you a signed CSR, aka. the certificate.
So I had an nginx config that returned a 301 to redirect to https all requests, except ACME challenges that got served from a directory acme.sh
had write access to.
And I had curly braces piece of nginx config for each host/project/domain name I was self hosting that pointed at the certificates, and at the actual backend that’s docker in some cases, PHP in other cases, or weird caching config.
I had a systemd timer that would run acme.sh cron
in the middle of the night and this would sometimes invoke systemctl nginx reload thanks to a sudoers rule.
I also have a DNS wildcard entry *.home.me.com CNAME router-home.me.com
This all works pretty well in the end. It’s a pain in the ass to setup for the first time on a new server, and there’s lots of moving parts that need to be set correctly.
Caddy - one stop https shop.
You spin it up either in docker or on bare metal with 80/443 exposed and reachable. You give it a data directory and a config like:
{
email [email protected]
}
dom1.home.example.com {
proxy_redirect http://localhost:5000
}
dom2.home.example.com {
proxy_redirect http://localhost:3000
}
When it starts up, it’ll get the certs for domains from the config, save them into the data dir and keep track of them and renew them.
Not needed are: a separate project for ACME protocol implementation, sudoers rules, acme challenge http configs, paths to certificate and key files, cipher enable/disable configs and so on.
You’re only missing HSTS lines and CAA DNS records and you get A+ on ssllabs tests out of the box.
Turns out it also has support for a bunch of features out of the box e.g. you can use “TLS on demand” to avoid having to configure it with a domain list in advance.
… it has some support for quic (haven’t tried personally).
It can support PROXY protocol with a plugin - in case you have HAproxy or nginx ssl_preread/proxy_protocol in front (plugins work the same as old school config options, you need to recompile but it’s easy with something called xcaddy … I’m using it, it’s working ok, it needs a separate port number)
It can support dynamic configuration through docker container labels , like traefik (haven’t tried - traefik also does ACME).
It also has a bunch of other more typical feature support like fcgi/php-fpm/scgi and ofcourse the ability to serve static files.
I’ll play with this a bit more and then try traefik next.