Optionally restart the service every week.

This commit is contained in:
Andrea Dell'Amico 2026-08-21 17:11:51 +02:00
parent 13f6679de3
commit ef104e06c4
Signed by: adellam
GPG Key ID: 147ABE6CEB9E20FF
6 changed files with 157 additions and 0 deletions

View File

@ -24,3 +24,20 @@ mailman_empty_list_header_matches:
The operation is idempotent. A list is modified only when its header-match
collection is empty; lists with one or more existing rules are left untouched.
## Verified weekly restart
The optional weekly restart performs separate stop and start operations. It
waits for both systemd and `mailman status` to confirm that Mailman has stopped
before starting it, then checks both signals again to confirm startup:
```yaml
mailman_enable_weekly_verified_restart: true
mailman_weekly_verified_restart_on_calendar: 'Sun *-*-* 04:00:00'
mailman_weekly_verified_restart_stop_timeout: 120
mailman_weekly_verified_restart_start_timeout: 120
```
The timer is deliberately not persistent, so a missed run is not executed
immediately after a server boot. Failures are recorded by systemd in the
`mailman-verified-restart.service` journal.

View File

@ -35,6 +35,14 @@ mailman_custom_templates:
- 'it/list:user:notice:welcome.txt'
mailman_enable_daily_notifications: true
# Periodically perform a verified stop/start cycle. The timer is disabled by
# default and, when enabled, uses the managed host's local timezone.
mailman_enable_weekly_verified_restart: false
mailman_weekly_verified_restart_on_calendar: 'Sun *-*-* 04:00:00'
mailman_weekly_verified_restart_stop_timeout: 120
mailman_weekly_verified_restart_start_timeout: 120
# Documentation that must be followed to configure the social auth providers
# https://django-allauth.readthedocs.io/en/latest/installation.html
mailman_use_social_account_providers: False

View File

@ -111,6 +111,50 @@
tags: [ 'mailman', 'mailman_conf' ]
- name: Configure the verified weekly Mailman restart
block:
- name: Install the verified Mailman restart script
ansible.builtin.template:
src: mailman-verified-restart.sh.j2
dest: /usr/local/sbin/mailman-verified-restart
owner: root
group: root
mode: '0750'
- name: Install the verified Mailman restart service
ansible.builtin.template:
src: mailman-verified-restart.service.systemd.j2
dest: /etc/systemd/system/mailman-verified-restart.service
owner: root
group: root
mode: '0644'
register: mailman_verified_restart_service_install
- name: Install the weekly Mailman restart timer
ansible.builtin.template:
src: mailman-verified-restart.timer.systemd.j2
dest: /etc/systemd/system/mailman-verified-restart.timer
owner: root
group: root
mode: '0644'
register: mailman_verified_restart_timer_install
- name: Reload systemd after installing the restart units
ansible.builtin.systemd:
daemon_reload: true
when: >-
mailman_verified_restart_service_install is changed or
mailman_verified_restart_timer_install is changed
- name: Enable and start the weekly Mailman restart timer
ansible.builtin.systemd:
name: mailman-verified-restart.timer
state: started
enabled: true
when: mailman_enable_weekly_verified_restart | bool
tags: [ 'mailman', 'mailman_conf', 'mailman_weekly_restart' ]
- name: Seed header matches on lists without existing rules
block:
- name: Create the Mailman administration scripts directory

View File

@ -0,0 +1,9 @@
[Unit]
Description=Verified stop and start cycle for Mailman 3
After=network-online.target remote-fs.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/mailman-verified-restart
TimeoutStartSec={{ (mailman_weekly_verified_restart_stop_timeout | int) + (mailman_weekly_verified_restart_start_timeout | int) + 30 }}

View File

@ -0,0 +1,68 @@
#!/bin/bash
set -uo pipefail
readonly SERVICE='mailman.service'
readonly MAILMAN='{{ mailman_bindir }}/mailman'
readonly CONFIG='{{ mailman_conf_dir }}/mailman.cfg'
readonly STOP_TIMEOUT={{ mailman_weekly_verified_restart_stop_timeout | int }}
readonly START_TIMEOUT={{ mailman_weekly_verified_restart_start_timeout | int }}
log()
{
printf 'mailman-verified-restart: %s\n' "$*"
}
mailman_is_stopped()
{
! systemctl is-active --quiet "${SERVICE}" &&
! "${MAILMAN}" -C "${CONFIG}" status >/dev/null 2>&1
}
mailman_is_started()
{
systemctl is-active --quiet "${SERVICE}" &&
"${MAILMAN}" -C "${CONFIG}" status >/dev/null 2>&1
}
wait_for_state()
{
local check_function="$1"
local timeout="$2"
local deadline=$((SECONDS + timeout))
while (( SECONDS < deadline )); do
if "${check_function}"; then
return 0
fi
sleep 1
done
"${check_function}"
}
log 'stopping Mailman'
if ! systemctl stop "${SERVICE}"; then
log 'ERROR: systemctl could not stop Mailman'
exit 1
fi
if ! wait_for_state mailman_is_stopped "${STOP_TIMEOUT}"; then
log 'ERROR: Mailman did not stop completely within the timeout; start skipped'
exit 1
fi
log 'Mailman is completely stopped'
systemctl reset-failed "${SERVICE}" >/dev/null 2>&1 || true
log 'starting Mailman'
if ! systemctl start "${SERVICE}"; then
log 'ERROR: systemctl could not start Mailman'
exit 1
fi
if ! wait_for_state mailman_is_started "${START_TIMEOUT}"; then
log 'ERROR: Mailman did not become active within the timeout'
exit 1
fi
log 'Mailman is active and its master process is running'

View File

@ -0,0 +1,11 @@
[Unit]
Description=Weekly verified restart of Mailman 3
[Timer]
OnCalendar={{ mailman_weekly_verified_restart_on_calendar }}
AccuracySec=1min
Persistent=false
Unit=mailman-verified-restart.service
[Install]
WantedBy=timers.target