xmpp_cert_sync: renew the XMPP certificate through Traefik
All checks were successful
deploy / ansible (push) Successful in 7m22s

The ejabberd certificate (asxp.io, conference., xmpp.) was issued by
hand and expires 2027-01-28 with nothing renewing it. Traefik now
obtains it alongside the sites' certificates, through a router that
only exists to request it, and a systemd path unit on ops pushes it to
services whenever acme.json changes, with a daily run as fallback.

The push uses its own SSH key, accepted from ops' VPC address only and
forced to xmpp-cert-install, which checks the certificate is valid for
another day and matches its key before replacing server.pem and
reloading ejabberd.

Two alerts: the sync hasn't succeeded for two days, or ejabberd serves
an older certificate than Traefik holds for six hours. The existing
expiry alert already covers port 5223.

Assisted-by: Claude:opus-5-5
This commit is contained in:
Sergei Poljanski 2026-11-13 08:16:00 +04:00
commit 5e009c4a47
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
11 changed files with 217 additions and 1 deletions

View file

@ -0,0 +1,20 @@
#!/bin/sh
# Managed by Ansible (role xmpp_cert_sync). Forced command of the
# xmpp_cert_sync key from asxpio-ops: read certificate chain + key on
# stdin, check it, install it for ejabberd and reload.
set -eu
umask 022
dir=/opt/xmpp/state/certs
tmp=$(mktemp "$dir/.server.pem.XXXXXX")
trap 'rm -f "$tmp"' EXIT
head -c 65536 > "$tmp"
# A certificate valid for at least another day, with its matching key
openssl x509 -in "$tmp" -noout -checkend 86400 >/dev/null
cert_pub=$(openssl x509 -in "$tmp" -noout -pubkey | sha256sum)
key_pub=$(openssl pkey -in "$tmp" -pubout | sha256sum)
[ "$cert_pub" = "$key_pub" ] || { echo "key does not match certificate" >&2; exit 1; }
chmod 0644 "$tmp"
mv "$tmp" "$dir/server.pem"
trap - EXIT
docker compose -f /opt/xmpp/docker-compose.yml exec -T ejabberd ejabberdctl reload_config
logger -t xmpp-cert-install "installed $(openssl x509 -in "$dir/server.pem" -noout -enddate)"