Caddy http(s) server - IMHO pretty ok

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. :slight_smile:

I’ll play with this a bit more and then try traefik next.

3 Likes

Caddy is the reverse proxy I was able to get working. It works very well and handles the certificate fine too. I’ve never been able to get nginx to work properly at anything beyond Hello World. pfsense with haproxy can do it but then you need pfsense, I say pfff to that.