Lets-Encrypt

使用 Let’s Encrypt certbot 時,如何僅在證書實際更新時才重新啟動/重新載入網路服務?

  • January 5, 2022

certbot命令提供了兩個在自動續訂後執行的掛鉤,來自文件:

 --post-hook POST_HOOK
                       Command to be run in a shell after attempting to
                       obtain/renew certificates. Can be used to deploy
                       renewed certificates, or to restart any servers that
                       were stopped by --pre-hook. This is only run if an
                       attempt was made to obtain/renew a certificate. If
                       multiple renewed certificates have identical post-
                       hooks, only one will be run. (default: None)
 --deploy-hook DEPLOY_HOOK
                       Command to be run in a shell once for each
                       successfully issued certificate. For this command, the
                       shell variable $RENEWED_LINEAGE will point to the
                       config live subdirectory (for example,
                       "/etc/letsencrypt/live/example.com") containing the
                       new certificates and keys; the shell variable
                       $RENEWED_DOMAINS will contain a space-delimited list
                       of renewed certificate domains (for example,
                       "example.com www.example.com" (default: None)

這個問題在這個(現已關閉的)LE 執行緒中進行了概述,基本上是關於最大限度地減少對服務的中斷。POST_HOOK每次嘗試更新時都會執行,即使沒有頒發證書,但只有一次。這使得不必要地重新啟動服務成為可能。DEPLOY_HOOK為每個成功的證書續訂執行。如果一個人使用DEPLOY_HOOK, 並且有多個證書,則每個服務可能會在一次足夠的情況下重新啟動多次。有關更新掛鉤的更多資訊,請點擊此處。

我使用一種完全不會中斷我的服務的發行方法,例如:

certbot certonly --webroot ...

或者

certbot certonly --dns-PROVIDER ...

我只想重新啟動/重新載入每個依賴服務一次,並且只有在其證書實際更改的情況下。

通過使用兩個鉤子和一個簡單的腳本來保存狀態,我能夠克服這個限制。例如,要重新載入 nginx,並在他們都使用的證書被更新時重新啟動 vsftpd:

certbot certonly ... \
   --deploy-hook '/usr/local/sbin/read-new-certs-services nginx --restart vsftpd' \
   --post-hook /usr/local/sbin/read-new-certs-services

腳本/usr/local/sbin/read-new-certs-services是這樣的:

#!/bin/sh

run_base=/run
dir_reloads="$run_base/new-cert-reloads"
dir_restarts="$run_base/new-cert-restarts"

if [ $# -gt 0 ]; then
   some=0
   dir="$dir_reloads"
   while [ $# -gt 0 ]; do
       case $1 in
           -h|--help)
               >&2 cat <<-'EOHELP'
                   Usage:

                     read-new-certs-services [-l|-s] service1 [[-l|-s] service2]
                     or
                     read-new-certs-services

                     When called without arguments, marked services will be reloaded or restarted.

                   Arguments:

                     -h, --help
                       This help.

                     -l, --reload
                       Mark all subsequently listed services for reloading.

                     -s, --restart
                       Mark all subsequently listed services for restarting.
                   EOHELP
               exit
               ;;
           -l|--reload)
               dir="$dir_reloads"
               ;;
           -s|--restart)
               dir="$dir_restarts"
               ;;
           *)
               if [ -n "$1" ]; then
                   some=1
                   run_file="$dir/$1"
                   if [ ! -f "$run_file" ] && ! install -D /dev/null "$run_file"; then
                       >&2 echo "Service could not be marked: $run_file"
                       exit 1
                   fi
               fi
               ;;
       esac
       shift
   done
   if [ $some -eq 0 ]; then
       >&2 echo 'No service(s) specified.'
       exit 1
   fi
   exit
fi

if [ -d "$dir_restarts" ]; then
   find "$dir_restarts" -mindepth 1 -printf '%P\t%p\n' | while IFS="$(printf '\t')" read -r svc run_file; do
       systemctl restart "$svc" && rm "$run_file"
       # no need to reload if restarting
       run_file="$dir_reloads/$svc"
       if [ -f "$run_file" ]; then
           rm "$run_file"
       fi
   done
fi

if [ -d "$dir_reloads" ]; then
   find "$dir_reloads" -mindepth 1 -printf '%P\t%p\n' | while IFS="$(printf '\t')" read -r svc run_file; do
       systemctl reload "$svc" && rm "$run_file"
   done
fi

這必須用於每個證書問題,以便他們不會使用衝突的重新啟動服務的方法。

您可以更改現有證書續訂以使用此方法,方法是編輯其/etc/letsencrypt/renewal/*.conf文件以包含如下[renewalparams]部分中的鉤子:

renew_hook = /usr/local/sbin/read-new-certs-services nginx -s vsftpd
post_hook = /usr/local/sbin/read-new-certs-services

引用自:https://serverfault.com/questions/1062849