ed9e942e42
Single bookworm-slim image running opendkim + panel + postfix under supervisord with enforced start ordering (spec 4): - build/Dockerfile: multi-stage static Go build; runtime installs postfix, opendkim, cyrus-sasl, supervisor, logrotate; unprivileged panel user (7.6.8). - build/supervisord.conf: priority ordering opendkim -> panel -> postfix; crashexit event listener terminates the container on any FATAL process. - build/postfix-wrapper.sh: waits for both milter sockets (test -S, 30s timeout) before `postfix start-fg`, exits non-zero on timeout. - panel: HTTP :8080 stub + /healthz, journal-milter socket stub (so the wrapper's readiness probe passes), log-tailer stub; SIGTERM graceful stop. Verified on the dev server: image builds, three processes live, panel serves the stub, wrapper waits for sockets, and an unrecoverable panel failure brings the container down cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
68 lines
1.6 KiB
Plaintext
68 lines
1.6 KiB
Plaintext
; SelfPost process supervision (spec 4).
|
|
;
|
|
; Start ORDER is enforced by priority=: OpenDKIM, then the panel (which opens
|
|
; the journal-milter socket), then the Postfix wrapper — which additionally
|
|
; blocks until both milter sockets are ready before starting Postfix.
|
|
;
|
|
; 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
|
|
|
|
[unix_http_server]
|
|
file=/run/supervisor.sock
|
|
chmod=0700
|
|
|
|
[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
|
|
|
|
[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
|
|
|
|
[eventlistener:crashexit]
|
|
command=/usr/local/bin/crashexit.py
|
|
events=PROCESS_STATE_FATAL
|
|
stderr_logfile=/dev/stderr
|
|
stderr_logfile_maxbytes=0
|