Caddy’s default TLS configuration is very good. It includes a lot of features that older and well-known servers like Nginx or Apache don’t enable by default.
From the tls module’s documentation:
Caddy implements these TLS features for you automatically. It is the only server to do so by default:
- Session identifiers
- Session ticket key rotation
- OCSP stapling
- Dynamic record sizing
- Application-layer protocol negotiation
- Forward secrecy
- HTTP/2 (for the HTTP server)
- Certificate management (including auto-renew)
- Man-In-The-Middle detection (for HTTPS sites)
Pretty awesome isn’t it? It also enables TLS 1.2 only by default and will support TLS 1.3 soon. FYI Caddy does not have its own TLS implementation by relies on the crypto/tls
module of Go.
Anyway, there are still 3 parameters that we can improve.
Certificate key type
By default, Caddy will use a 2048 bits RSA key to sign Let’s encrypt certificates. This is a sane default and great for compatibility.
I prefer elliptic curve, so I use 256 bits ECDSA certificates. I’ve been running some for over a year now with Nginx and Let’s Encrypt without issues.
Here’s how to change the key type:
tls {
key_type p256
}
I had to remove the content of /etc/ssl/caddy
in order for Caddy to regenerate with a new key after a restart.
Cipher suites
Edit (04/03/2019): Caddy 0.11.5 is out, with TLS 1.3 support (enabled by default). It removes non-AEAD ciphers by default for both TLS 1.2 and 1.3. You can’t customise TLS 1.3 ciphers with the Go implementation (Go 1.12), but you can with TLS 1.2. There is no need to specify the cipher
option unless you want to enabled CBC ciphers for compatibility.
Caddy support these ciphers by default:
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-WITH-CHACHA20-POLY1305
ECDHE-RSA-WITH-CHACHA20-POLY1305
ECDHE-RSA-AES256-CBC-SHA
ECDHE-RSA-AES128-CBC-SHA
ECDHE-ECDSA-AES256-CBC-SHA
ECDHE-ECDSA-AES128-CBC-SHA
RSA-AES256-CBC-SHA
RSA-AES128-CBC-SHA
ECDHE-RSA-3DES-EDE-CBC-SHA
RSA-3DES-EDE-CBC-SHA
They’re pretty good for default ciphers, but we really want to avoid 3DES and RSA key exchange (I’m not talking about the certificate here).
Since we enabled ECDSA certificates earlier, we can also remove RSA from our cipher suite.
This is the one I use:
tls {
ECDHE-ECDSA-WITH-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-CBC-SHA ECDHE-ECDSA-AES256-CBC-SHA
}
If you use a RSA certificate, you can copy/paste this and replace ECDSA with RSA.
I keep AES CBC for now, for compatibility. I’ll probably remove it in the next few years. Note that HTTP/2 and TLS 1.3 already blacklist it.
ECDHE curve type
By default, Caddy enables X25519
and p256
curves, which is great. I like to support more curves so I added p384
and p521
.
tls {
curves X25519 p521 p384 p256
}
Bonus tip: use import
Tip
Since I have to add this tls {}
block in all my vhosts, I just put it in a tls.conf
file and then add import tls.conf
in all my vhosts.
That’s all! Caddy is a modern and secure-by-default web server, it’s my new favorite thing! Expect more posts about it in the future.