acme.sh: add abort service command and improve interactive messages

For runs started interactively, improve messaging and allow a run to be
aborted with `service acme abort`.

Signed-off-by: Aditya Bhargava <rightaditya@gmail.com>
This commit is contained in:
Aditya Bhargava
2025-09-29 18:05:19 -04:00
committed by Toke Høiland-Jørgensen
parent 76b676e4eb
commit fbf38647fd
2 changed files with 81 additions and 9 deletions

View File

@@ -39,6 +39,53 @@ link_certs() {
fi
}
handle_signal() {
local notify_op=$1
local label_op=$2
wait_notify() {
# wait for acme.sh child job to die, *then* notify about status
wait
log warn "$label_op aborted: $main_domain"
$NOTIFY "${notify_op}-failed"
exit 1
}
trap wait_notify TERM
# try to kill the cgroup
local cgroup=$(cut -d : -f 3 /proc/$$/cgroup)
if [[ "$cgroup" == '/services/acme/*' ]]; then
# send SIGTERM to all processes in this process's cgroup. this
# relies on procd's having set up the cgroup for the instance.
read -r -d '' pids < /sys/fs/cgroup${cgroup}/cgroup.procs
kill -TERM $pids 2> /dev/null
fi
# if we're here, either the cgroup wasn't as exected to be set up by
# procd or killing the cgroup PIDs failed. try to kill the process
# group, assuming this process is the group leader. this is actually
# unlikely since procd doesn't set service PGIDs (so they aren't group
# leaders).
kill -TERM -$$ 2> /dev/null
# if we're here, cgroup-based killing was avoided or didn't work and
# PGID-based killing didn't work. fall back to the raciest option.
trap "" TERM
term_descendants() {
local pids=$@
local pid=
# `pgrep -P` returns nothing if given a non-existent PID
# (even if the PID has live children), so children must
# be killed first
for pid in $pids; do
term_descendants $(pgrep -P "$pid")
kill -TERM "$pid" 2> /dev/null
done
}
term_descendants $(jobs -p)
wait_notify
}
case $1 in
get)
set --
@@ -67,10 +114,11 @@ get)
else
set -- "$@" --renew --home "$state_dir" -d "$main_domain"
log info "$ACME $*"
trap 'log err "Renew failed: SIGINT";$NOTIFY renew-failed;exit 1' INT
$ACME "$@"
trap "handle_signal renew Renewal" INT TERM
$ACME "$@" &
wait $!
status=$?
trap - INT
trap - INT TERM
case $status in
0)
@@ -141,12 +189,13 @@ get)
set -- "$@" --issue --home "$state_dir"
log info "$ACME $*"
trap 'log err "Issue failed: SIGINT";$NOTIFY issue-failed;exit 1' INT
trap "handle_signal issue Issuance" INT TERM
"$ACME" "$@" \
--pre-hook "$NOTIFY prepare" \
--renew-hook "$NOTIFY renewed"
--renew-hook "$NOTIFY renewed" &
wait $!
status=$?
trap - INT
trap - INT TERM
case $status in
0)

View File

@@ -13,7 +13,8 @@ LOG_TAG=acme
# shellcheck source=net/acme/files/functions.sh
. "$IPKG_INSTROOT/usr/lib/acme/functions.sh"
extra_command "renew" "Start a certificate renew"
extra_command "abort" "Abort running certificate issuances/renewals"
extra_command "renew" "Run certificate issuances/renewals"
delete_nft_rule() {
if [ "$NFT_HANDLE" ]; then
@@ -136,6 +137,7 @@ get_cert() {
load_options "$section"
load_credentials() {
# use `eval` to correctly strip quotes around credential values
eval procd_append_param env "$1"
}
config_list_foreach "$section" credentials load_credentials
@@ -175,15 +177,20 @@ start_service() {
}
service_started() {
echo "Certificate renewal enabled via cron. To renew now, run '/etc/init.d/acme renew'."
echo 'Nightly certificate renewal enabled. To renew now, run `service acme renew`.'
}
stop_service() {
sed -i '\|/etc/init.d/acme|d' /etc/crontabs/root
running && stop_aborted="Running certificate renewal(s) aborted and a"
}
service_stopped() {
echo "Certificate renewal is disabled."
if enabled; then
untilboot=' until next boot. To disable permanently, run `service acme disable`'
fi
echo "${stop_aborted:-A}utomatic nightly renewal disabled$untilboot."
echo 'To re-enable nightly renewal, run `service acme start`. To issue/renew now, run `service acme renew`.'
}
service_triggers() {
@@ -201,5 +208,21 @@ load_and_run() {
}
renew() {
echo "Starting certificate issuance/renewal in the background; see system log for progress."
echo 'Issuances/renewals can be aborted with `service acme abort`.'
rc_procd load_and_run
}
abort() {
procd_lock
if running "$@"; then
procd_kill "$(basename ${basescript:-$initscript})" "$1"
echo "Aborting certificate issuance(s)/renewal(s); see system log for confirmation."
elif [ -z "$1" ]; then
echo "No certificate issuances/renewals running to abort!"
exit 1
else
echo "No certificate issuance/renewal \"$1\" running to abort!"
exit 1
fi
}