; SelfPost process supervision. ; ; Start ORDER is enforced by priority=: OpenDKIM, then the panel (which opens ; the sender check's and the journal-milter's sockets), then the Postfix ; wrapper — which additionally blocks until the milter sockets are ready ; before starting Postfix. (supervisor 4.2.5, docs/configuration.rst, ; [program:x] "priority": "the start and shutdown ordering"; supervisor/ ; supervisord.py, runforever(), transitions every group in that order in one ; pass, with no wait for a program to be ready.) ; ; If any managed process exhausts its restart retries (FATAL), the crashexit ; event listener brings the whole container down so Docker's restart policy can ; recreate it cleanly, rather than lingering with a dead component. [supervisord] nodaemon=true user=root logfile=/dev/null logfile_maxbytes=0 pidfile=/run/supervisord.pid loglevel=info ; The control socket is reachable by the shared `selfpost` group so the panel ; (running as the unprivileged `panel` user) can ask supervisord to send ; OpenDKIM a reload signal after it rewrites the DKIM tables. It is still ; unreachable by world; only root and the two SelfPost services are in the ; group. No HTTP auth is configured because access is gated by socket ; permissions, not the network. (supervisor 4.2.5, docs/configuration.rst, ; [unix_http_server]: chmod and chown set the socket's mode and owner; without ; username and password no authentication is asked.) [unix_http_server] file=/run/supervisor.sock chown=root:selfpost chmod=0770 [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=unix:///run/supervisor.sock [program:opendkim] command=/usr/sbin/opendkim -f -x /etc/opendkim.conf priority=100 autostart=true autorestart=true startretries=3 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 ; user=panel also gives the panel its supplementary groups, selfpost and ; postdrop (build/Dockerfile): supervisor 4.2.5, supervisor/options.py, ; drop_privileges(), os.setgroups() from the user's memberships in ; grp.getgrall(). [program:panel] command=/usr/local/bin/panel user=panel priority=200 autostart=true autorestart=true startretries=3 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:postfix] command=/usr/local/bin/postfix-wrapper.sh priority=300 autostart=true autorestart=true startretries=3 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 ; One-shot reload helper. The panel runs unprivileged and cannot run `postfix ; reload` itself, and it cannot signal the Postfix master directly: `postfix ; start-fg` forks a separate master process, so a signal to the supervised ; foreground process never reaches it (unlike OpenDKIM, which runs in the ; foreground as the supervised process itself). Instead the panel asks ; supervisord — over the group-accessible control socket — to run this program, ; which executes the canonical `postfix reload` as root. autostart is off (it ; only runs on demand) and a fast, clean exit is expected, so it never trips the ; crashexit listener. (start-fg: see build/postfix-wrapper.sh. supervisor ; 4.2.5, supervisor/process.py, Subprocess.finish(): with startsecs=0 no exit ; counts as "too quickly", so even a failed run ends EXITED - never BACKOFF, ; never FATAL.) [program:postfix-reload] command=/usr/sbin/postfix reload autostart=false autorestart=false startsecs=0 startretries=1 exitcodes=0 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 ; TLS-certificate refresh. Once a day it compares the certificate the ; reverse-proxy renews in the read-only mount with the copy Postfix reads, and ; when they differ copies it again and runs `postfix reload`. ; Long-running (it loops), runs as root so it can reload Postfix, and never exits ; non-zero, so it neither trips the crashexit listener nor needs restarting. [program:cert-reload] command=/usr/local/bin/postfix-cert-reload.sh priority=400 autostart=true autorestart=true startsecs=0 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 ; Periodic logrotate for /data/log/mail.log (daily, 7-14 files kept in the ; image). Runs as root so logrotate can read/rotate the log. Exits non-zero when ; the config is group/other-writable (logrotate would ignore it silently); ; autorestart surfaces BACKOFF on the Status page. [program:logrotate] command=/usr/local/bin/logrotate-loop.sh priority=400 autostart=true autorestart=true startsecs=0 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 ; supervisor 4.2.5, supervisor/process.py: a program enters FATAL only from ; BACKOFF, once startretries are spent; a stop asked of supervisord ends in ; STOPPED (Subprocess.finish(), self.killing), which this listener never sees. [eventlistener:crashexit] command=/usr/local/bin/crashexit.py events=PROCESS_STATE_FATAL stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0