ops/tls.md: document TLS configuration

This commit is contained in:
Drew DeVault 2024-01-23 12:59:42 +01:00
parent d04527040e
commit e19269de1a
1 changed files with 116 additions and 0 deletions

116
ops/tls.md Normal file
View File

@ -0,0 +1,116 @@
---
title: TLS documentation
---
There are two current approaches to maintaining TLS certificates:
1. [uacme](https://github.com/ndilieto/uacme)
2. [tlstunnel](https://sr.ht/~emersion/tlstunnel/)
Presently the latter is only used for pages.sr.ht.
## uacme
The configuration we use for uacme is a fucking nightmare, but it does work and
is pretty reliable. In the future it might be nice to switch to tlstunnel for
everything or at least put some more work into the uacme setup.
### Set up
We have a bunch of shell commands that sets up uacme on a server:
```
doas apk add uacme openssl moreutils
doas useradd -md /var/lib/acme -s /sbin/nologin acme
doas mkdir -p /etc/ssl/uacme/private /var/www/.well-known/acme-challenge
doas chown acme:acme /etc/ssl/uacme /etc/ssl/uacme/private
doas chmod g+rX /etc/ssl/uacme /etc/ssl/uacme/private
doas chown acme:acme /var/www/.well-known/acme-challenge
doas touch /var/log/acme.log
doas chown acme:acme /var/log/acme.log
doas vim /usr/local/bin/acme-update-certs
```
Contents of acme-update-certs, edit as necessary:
```
#!/bin/sh
exec >>/var/log/acme.log 2>&1
date
stats() {
cert="/etc/ssl/uacme/$1/cert.pem"
if ! [ -e "$cert" ]
then
return
fi
expiration=$(date -d"$(openssl x509 -enddate -noout -in "$cert" \
| cut -d= -f2)" -D'%b %d %H:%M:%S %Y GMT' +'%s')
printf '# TYPE certificate_expiration gauge\n'
printf '# HELP certificate_expiration Timestamp when SSL certificate will expire\n'
printf 'certificate_expiration{instance="%s"} %s\n' "$1" "$expiration"
}
acme() {
site=$1
shift
/usr/bin/uacme -v -h /usr/share/uacme/uacme.sh issue $site $* || true
stats $site | curl --data-binary @- https://push.metrics.sr.ht/metrics/job/$site
}
acme DOMAIN SUBDOMAIN...
```
```
doas nginx -s reload
doas chmod +x /usr/local/bin/acme-update-certs
doas usermod -aG acme nginx
doas -u acme uacme new sir@cmpwn.com
doas -u acme crontab -e
```
Contents of crontab:
```
MAILTO=sir@cmpwn.com
0 0 * * * chronic /usr/local/bin/acme-update-certs
```
Then update the nginx configuration, commenting out the includes for
port443.conf and \*-ssl.conf.
```
doas -u acme /usr/local/bin/acme-update-certs
cat /var/log/acme.log
```
Verify that acme.log looks okay, then uncomment the relevant parts of the nginx
configuration.
```
doas chmod -R g+rX /etc/ssl/uacme /etc/ssl/uacme/private
doas nginx -s reload
# verify TLS configuration
```
Note: wildcard certificates are possible with uacme, but it's a bloody nightmare
so if you want this it's best to go with tlstunnel instead.
### Monitoring
TLS certificate expiration and renewal is monitored by metrics.sr.ht:
[![](https://metrics.sr.ht/chart.svg?title=Days%20until%20certificate%20expiration&query=(certificate_expiration%20-%20time())/60/60/24&since=336h&label={{.instance}}&height=3.5&min=0)](https://metrics.sr.ht/graph?g0.expr=(certificate_expiration%20-%20time())&g0.tab=0&g0.stacked=0&g0.show_exemplars=0&g0.range_input=2w)
The acme update script pushes the expiration date to push.metrics.sr.ht whenever
the cronjob runs. If any certificate's expiration date falls below 1 week, the
"SSL expiration" alarm is raised.
## tlstunnel
tlstunnel automatically adds zero-configuration TLS to arbitrary TCP sockets
using SNI and the PROXY protocol. It is currently used for pages.sr.ht.
### Monitoring
Presently none; see https://todo.sr.ht/~emersion/tlstunnel/24