Let a server service carry helper scripts and timers, starting with UseSend's cert refresh
This commit is contained in:
1 parent
a987cbab66
commit
95fa480469
9 files changed
+304
-59
No files matched your search
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/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)"
|
||||
Reference in new issue
Block a user