Files
Panama/server/vps/UseSend/refresh-smtp-certs
T

54 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Keep the UseSend SMTP proxy's TLS certificate in step with NPM's Let's Encrypt store.
#
# The proxy refuses AUTH until STARTTLS succeeds, so an expired or mismatched cert
# takes down ALL outbound mail for every app that sends through it -- and it fails
# with a bare TLS error that never mentions certificates. Hence this timer.
#
# Copies rather than bind-mounts because NPM mounts its letsencrypt tree with :Z
# (private SELinux category) and two consumers on one path fight over the label.
#
# Uses npm-43 because it carries *.usesend.gbrown.org, the SAN that validates
# smtp.usesend.gbrown.org. A wildcard matches exactly ONE label, so *.gbrown.org
# alone would not cover it.
set -euo pipefail
SRC=$HOME/Server/Nginx_Proxy_Manager/volumes/letsencrypt/live/npm-43
DST=$HOME/Server/UseSend/certs
CONTAINER=usesend-smtp-server
fp() { openssl x509 -in "$1" -noout -fingerprint -sha256 2>/dev/null | cut -d= -f2; }
certpub(){ openssl x509 -in "$1" -noout -pubkey 2>/dev/null | openssl sha256 | awk '{print $2}'; }
keypub() { openssl pkey -in "$1" -pubout 2>/dev/null | openssl sha256 | awk '{print $2}'; }
[ -r "$SRC/fullchain.pem" ] && [ -r "$SRC/privkey.pem" ] || {
echo "source cert unreadable under $SRC -- did NPM move it?" >&2; exit 1; }
src_fp=$(fp "$SRC/fullchain.pem")
dst_fp=$(fp "$DST/fullchain.pem" 2>/dev/null || true)
if [ -n "$dst_fp" ] && [ "$src_fp" = "$dst_fp" ]; then
echo "cert unchanged (${src_fp:0:17}...); nothing to do"
exit 0
fi
# Refuse to install a half-renewed pair: certbot writes the two files separately, so
# a run that lands between them would leave the proxy with a key that is not its cert.
if [ "$(certpub "$SRC/fullchain.pem")" != "$(keypub "$SRC/privkey.pem")" ]; then
echo "source cert and key do not match -- renewal probably mid-flight, retrying next run" >&2
exit 0
fi
echo "cert changed (${dst_fp:0:17}... -> ${src_fp:0:17}...), installing"
# -L dereferences: live/ entries are symlinks into ../../archive/, outside this copy.
cp -L "$SRC/fullchain.pem" "$DST/fullchain.pem.new"
cp -L "$SRC/privkey.pem" "$DST/privkey.pem.new"
chmod 644 "$DST/fullchain.pem.new"
chmod 640 "$DST/privkey.pem.new"
mv -f "$DST/fullchain.pem.new" "$DST/fullchain.pem"
mv -f "$DST/privkey.pem.new" "$DST/privkey.pem"
echo "restarting $CONTAINER"
podman restart "$CONTAINER" >/dev/null
echo "done; cert now valid until $(openssl x509 -in "$DST/fullchain.pem" -noout -enddate | cut -d= -f2)"