From fa2d31f7ca75b8ae9de5d830413bed44511aeb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20D=C3=BCsterhaupt?= Date: Fri, 15 May 2026 13:28:51 +0200 Subject: [PATCH] Deduplicate service restarts after certificate deployment --- dyntls.sh | 88 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/dyntls.sh b/dyntls.sh index b6f12de..b916f66 100644 --- a/dyntls.sh +++ b/dyntls.sh @@ -1016,31 +1016,16 @@ _ProvideCertDomainService() { _log "Certificates and keys provided for service '$DisplayName'." 2 - # Restart or reload the service if configured + # Queue "Restart/reload the service" if configured if [ "$RestartFlag" -eq 1 ] && [ -n "$Service" ]; then [ "$RestartMode" = "restart" ] || [ "$RestartMode" = "reload" ] || RestartMode="restart" - - if [ -n "$ServiceOwner" ] && [ "$ServiceOwner" != "root" ]; then - _log "Reloading service '$Service' as non-root user '$ServiceOwner'..." 1 - if sudo -u "$ServiceOwner" XDG_RUNTIME_DIR="/run/user/$(id -u "$ServiceOwner")" \ - systemctl --user "$RestartMode" "$Service.service"; then - _log "Service '$DisplayName' successfully $RestartMode-ed as '$ServiceOwner'." 2 - else - _log "Error while $RestartMode-ing service '$DisplayName'." 4 - MyIsError=1 - fi - else - _log "Reloading service '$Service' as root..." 1 - if systemctl "$RestartMode" "$Service.service"; then - _log "Service '$DisplayName' successfully $RestartMode-ed as root." 2 - else - _log "Error while $RestartMode-ing service '$DisplayName'." 4 - MyIsError=1 - fi - fi + action_entry="${RestartMode}:${ServiceOwner}:${Service}:${DisplayName}" + PendingServiceActions="${PendingServiceActions}${action_entry}\n" + _log "Queued service action: mode=$RestartMode, service=$Service, owner=$ServiceOwner, name=$DisplayName" 1 else _log "No restart required for service '$DisplayName'." 2 fi + done < _reload_webserver() +# SDuesterhaupt: 2026-05-15 - Reload or restart queued services after certificate deployment +# +# Executes the queued PendingServiceActions collected during certificate +# provisioning, deduplicates identical actions and runs each service action +# only once per update run. +# +# Returns 0 on success or 1 if at least one service action failed. +_reload_services() { + _log "Enter the function '_reload_services()'..." 1 + + [ -n "$PendingServiceActions" ] || { + _log "No queued service actions to process." 1 + _log "Leave the function '_reload_services()'..." 1 + return 0 + } + + MyIsError=0 + + _log "Processing queued service actions..." 1 + + PendingServiceActionsUnique=$(printf '%b' "$PendingServiceActions" | awk '!seen[$0]++') + + while IFS=':' read -r RestartMode ServiceOwner Service DisplayName || [ -n "$Service" ]; do + [ -n "$Service" ] || continue + + if [ -n "$ServiceOwner" ] && [ "$ServiceOwner" != "root" ]; then + _log "Reloading service '$Service' as non-root user '$ServiceOwner'..." 1 + if sudo -u "$ServiceOwner" XDG_RUNTIME_DIR="/run/user/$(id -u "$ServiceOwner")" \ + systemctl --user "$RestartMode" "$Service.service"; then + _log "Service '$DisplayName' successfully $RestartMode-ed as '$ServiceOwner'." 2 + else + _log "Error while $RestartMode-ing service '$DisplayName'." 4 + MyIsError=1 + fi + else + _log "Reloading service '$Service' as root..." 1 + if systemctl "$RestartMode" "$Service.service"; then + _log "Service '$DisplayName' successfully $RestartMode-ed as root." 2 + else + _log "Error while $RestartMode-ing service '$DisplayName'." 4 + MyIsError=1 + fi + fi + done < _reload_services() + + # SDuesterhaupt: 2025-09-14 - Add a new certificate for a domain or SAN list # # Normalizes DYNTLS_DOMAINS input, @@ -1434,6 +1471,8 @@ _remove_cert() { _update_cert() { _log "Enter the function '_update_cert()'..." 1 + PendingServiceActions="" + ########################### # 1. Calculate expiration window ########################### @@ -1526,7 +1565,14 @@ _update_cert() { fi ########################### - # 4. Mail notification if enabled + # 4. Reload service(s) if needed + ########################### + if [ -n "$PendingServiceActions" ]; then + _reload_services || MyIsError=1 + fi + + ########################### + # 5. Mail notification if enabled ########################### if $DYNTLS_SEND_MAIL; then Subject="Certificate check on $HOSTNAME"