Generated: 2026-05-13. Sources: upstream GitHub issues (open + recently closed),
Debian salsa.debian.org/debian/opendkim patch queue, FreeBSD ports rc script,
OpenBSD ports Makefile + rc script, Gentoo initd (404 — file not found at
enumerated path).
Cross-referenced against:
- SCOPE.md goals
git log --oneline 92951a3a..HEAD(our fork history)- Working tree (grep/source inspection)
| Priority | Source | ID / File | Summary | Recommendation | Notes |
|---|---|---|---|---|---|
| 1 | Debian patch | cve-2020-12272.patch |
Missing character-set validation on the d= tag value in DKIM-Signature header. A crafted signature with illegal chars (e.g. newline, NUL, shell metachar) passes through dkim_process_set() unrejected. |
Apply to libopendkim/dkim.c around the d= NULL check (~line 712). Add loop: reject any char not in [A-Za-z0-9._-]. |
Upstream never merged this Debian-specific patch. Our tree has no such loop — verified by grep. |
| 2 | GitHub issue | #260 / CVE-2020-35766 | Insecure fixed /tmp/testkeys path in test harness. t-testdata.h defines KEYFILE as /tmp/testkeys; t-setup.c creates it with bare fopen() — susceptible to symlink/TOCTOU attack. No runtime daemon impact; exploitable only during test execution. Distinct from CVE-2022-48521 (A-R header ordering, fixed in f238cdcd). |
Applied (commit cve-2020-35766): changed KEYFILE to relative "testkeys" and replaced fopen() with open(O_CREAT|O_EXCL|O_NOFOLLOW) + fdopen() in t-setup.c. PR #260 diff reviewed before applying. |
✓ Fixed |
| 3 | GitHub issue | #185 | Authentication-Results headers from external sources are stripped using wrong ordinal numbering, allowing a crafted inbound message to survive with a fake A-R header that OpenDKIM believes it already removed. Security bypass in verification mode. |
Already fixed by commit f238cdcd (CVE-2022-48521): reverse-order traversal with stable ordinal tracking. Issue is CLOSED upstream. |
✓ Fixed (f238cdcd) |
| Priority | Source | ID / File | Summary | Recommendation | Notes |
|---|---|---|---|---|---|
| 4 | Debian patch | conf_refcnt.patch |
dkimf_config_free() contains assert(conf->conf_refcnt == 0) at opendkim/opendkim.c:5374. Under certain reload/close timing the count may be non-zero, aborting the daemon. |
Applied: replaced assert with syslog(LOG_CRIT, …); return; guard — never aborts, logs if it fires (improvement over Debian's silent removal). |
✓ Fixed |
| 5 | Debian patch | mlfi_close.patch |
#ifdef QUERY_CACHE block in mlfi_close() dereferences cc->cctx_config after the if (cc != NULL) block that decrements the refcount and frees cc. Use-after-free (or NULL deref). |
Applied: removed all 6 #ifdef QUERY_CACHE blocks from opendkim.c (2 global variable declarations, 1 in config-load, 1 in main init, 1 in dkimf_config_load, 1 the use-after-free block in mlfi_close). QUERY_CACHE was never defined. |
✓ Fixed |
| 6 | Debian patch | insheader.patch |
All calls to dkimf_insheader(ctx, 1, …) should be dkimf_insheader(ctx, 0, …). Index 1 inserts after the first existing header; index 0 inserts before all headers. Affects Authentication-Results, DKIM-Signature, and X-OpenDKIM insertion order. |
Applied: changed all five dkimf_insheader(ctx, 1, → dkimf_insheader(ctx, 0, (lines 3266, 3700, 11678, 12507, 12557 at time of patch). |
✓ Fixed |
| 7 | Debian patch | fix-miltertest-data.patch |
miltertest/miltertest.c: the mt.data() function asserts STATE_DATA (wrong — it transitions to DATA from ENVRCPT) and the mt.header() function asserts STATE_ENVRCPT (wrong — headers come after DATA). The two state checks are swapped. |
Applied: swapped the two assertions to match SMTP sequencing. Patch by David Buergin (Debian). | ✓ Fixed |
| 8 | Debian patch | fix-miltertest-eom-check-smtpreply.patch |
miltertest.c:3693–3694: when MT_SMTPREPLY is checked, esc and text are passed directly to snprintf even when NULL. Undefined behaviour (NULL pointer in %s format argument is not guaranteed to produce "(null)" on all platforms). |
Applied: guarded both args — esc == NULL ? "" : esc and text == NULL ? "" : text. Patch by David Buergin (Debian). |
✓ Fixed |
| 9 | GitHub issue | #222 / #223 | Segfault when Minimum 100% is set in config and an inbound message has an empty body. Division by zero: (100 * canonlen) / bodylen when bodylen == 0. |
Applied: wrap the entire sigmin block in if (bodylen) — empty body is never partial. Fix by Yasuhito FUTATSUKI (upstream PR #223). |
✓ Fixed |
| 10 | GitHub issue | #229 / #230 | dkimf_config_load() sign-table consistency walk: dkimf_db_walk() error return not checked; second SigningTable field (signer) not marked optional, causing walk to fail on valid single-field entries. |
Already fixed in our tree: _walkret captures the return, dbd[1] marked DKIMF_DB_DATA_OPTIONAL, post-loop _walkret == -1 check present. Applied test config fix (file: → refile:) so the walk path is exercised. Fix by Yasuhito FUTATSUKI (upstream PR #230). |
✓ Fixed |
| 11 | GitHub issue | #262 | DKIM_STAT_KEYFAIL not handled in mlfi_eoh() or mlfi_eom() inner switch; Lua hook variable shadowed status from dkim_eoh(); status=dkimf_libstatus() stored sfsistat in int; DKIMF_STATUS_KEYFAIL missing from A-R check and final status switch. |
Applied: added DKIMF_STATUS_KEYFAIL constant (renumbered 3–9); added status string; fixed Lua hook shadow (hkstat); added DKIM_STAT_KEYFAIL cases to both switches; fixed ret/status confusion; added KEYFAIL to A-R check and outer switch; initialised ret at declaration. Fix by Yasuhito FUTATSUKI (upstream PR #262). |
✓ Fixed |
| Priority | Source | ID / File | Summary | Recommendation | Notes |
|---|---|---|---|---|---|
| 12 | GitHub issue | #233 / #234 | When a DKIM_SIGFLAG_IGNORE-marked signature is encountered, OpenDKIM records dkim=fail in Authentication-Results instead of dkim=policy. RFC 8601 §2.7.1 distinguishes these results. |
Applied: cache flags in sigflag; check DKIM_SIGFLAG_IGNORE first and set result = "policy" before the pass/fail chain. Fix by Yasuhito FUTATSUKI (upstream PR #234). |
✓ Fixed |
| 13 | GitHub issue | #244 | dfc->mctx_domain == NULL in dkimf_add_signrequest() always evaluates false — mctx_domain is a char array, not a pointer. Should check mctx_domain[0] == '\0'. vbr.c fix not applicable (removed per SCOPE.md). |
Applied: dfc->mctx_domain == NULL → dfc->mctx_domain[0] == '\0'. Fix by Jim C. (upstream PR #244). |
✓ Fixed |
| 14 | Debian patch | nsupdate_output.patch |
opendkim-genzone -u (nsupdate mode) outputs bare key data without the required v=DKIM1; k=rsa; prefix. (255-byte chunking was already present in our tree.) Also adds -M flag to restrict key to email use — skipped, no mailrestrict/subdomains variable in our genzone. |
Applied: added v=DKIM1; k=rsa; p= to the nsupdate TXT format string. |
✓ Fixed |
| 15 | Debian patch | suppress-brackets-syslog.patch |
Startup syslog message opendkim vX.Y.Z starting () prints empty parentheses when no arguments are logged. |
Applied: guard parens with argstr[0] == '\0' ternaries — omit () entirely when no args. |
✓ Fixed |
| Source | ID / File | Reason |
|---|---|---|
| Debian patch | fix-RSA_Sign-call.patch |
Patches RSA_sign() type mismatch — function replaced by EVP APIs in our fork (Session 6). |
| Debian patch | 2048bit-genkey.patch |
Default key size already enforced at 2048 bits in our fork (MinKeyBits, commit 0e4aad7d). |
| Debian patch | replace-headers.patch |
Adds ReplaceHeaders config inside #ifdef _FFR_REPLACE_RULES. Feature removed per SCOPE.md. |
| Debian patch | fix-genzone-subdomains.patch |
Fixes a subdomains flag logic block in opendkim-genzone.c. Our genzone has no subdomains variable — the feature was not ported. N/A. |
| Debian patch | lua-5.3.patch |
lua_dump() extra-arg and luaL_newlib already handled in our Lua 5.4 port (commit a87e550b, opendkim-lua.c:538 confirmed). |
| Debian patch | ares-missing-space.patch |
c-ares / libar removed per SCOPE.md (commit c3f6e3f9). |
| Debian patch | rev-ares-deletion.patch |
libar removed. |
| Debian patch | opendkim-genkey-typo.patch |
Upstream man-page typo in .8.in — we have rewritten man pages, not the autotools .in versions. |
| GitHub issue | #255, #235, #236 | Website / opendkim.org dead links. Not software. |
| GitHub issue | #258, #257 | SingleAuthResult in sample config — already absent from our opendkim.conf.sample. |
| GitHub issue | #248, #251 | MySQL password / auth plugin issues — MySQL backend removed per SCOPE.md. |
| GitHub issue | #224 | librbl/rbl.c typo — librbl removed per SCOPE.md. |
| GitHub issue | #237 | Python twisted.internet.defer.returnValue — not C code, not in scope. |
| GitHub issue | #249 | macOS port group membership issue — macOS is not a target platform. |
| GitHub issue | #253 | VSZ memory growth under load test — operational question, not a code defect. |
| GitHub issue | #165 | Systemd network-online.target — already in our debian/opendkim.service. |
| GitHub issue | #38 | /var/run vs /run path — already resolved by RuntimeDirectory=opendkim in our service unit. |
| GitHub issue | #242 | AlwaysAddARHeader default — feature request, out of scope for this session. |
| GitHub issue | #241 | Lua final hook header mutation — feature request, out of scope. |
| GitHub issue | #232 | Config option to require d= matches From: — feature request, out of scope. |
| GitHub issue | #246 | Ed25519 in opendkim-genkey — already added in our fork (commit 3858b88d). |
| GitHub issue | #243 | Ed25519 tests — partially addressed; dkim_free() memory leak subpoint needs separate investigation. |
| GitHub issue | #221 | Config option case sensitivity — documentation / user question, not a defect. |
| GitHub issue | #225 | Test failures on upstream autotools build — our CMake build passes. Not applicable. |
Comparing FreeBSD milter-opendkim.in and OpenBSD opendkim.rc against our
debian/opendkim.service. Items marked ★ are currently missing from our service unit.
-
★ Additional systemd hardening directives. Our unit has
ProtectSystem=strictandProtectHome=truebut is missingNoNewPrivileges=true,PrivateTmp=true,LockPersonality=true,RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6, andMemoryDenyWriteExecute=true. FreeBSD and OpenBSD achieve equivalent isolation throughjail(8)andpledge(2)— on Linux, systemd sandboxing directives are the idiomatic equivalent. -
Socket cleanup on stop. FreeBSD's
stop_postcmdunconditionally removes the Unix domain socket file (rm -f "$socket") whensocket_type == local|unix. OurRuntimeDirectory=opendkimcauses systemd to clean/run/opendkim/on stop, so this is already covered on systemd systems. Worth documenting for any future non-systemd init script (e.g. OpenRC for Gentoo/Alpine). -
PidFile auto-detection from opendkim.conf. FreeBSD reads the
PidFilevalue directly from the config file at rc-script runtime (get_pidfile_from_conf), rather than hardcoding/var/run/milteropendkim/pid. This avoids divergence when the admin changesPidFilein opendkim.conf. Our systemd unit does not manage a pidfile (Type=simple), so this is irrelevant for systemd but matters for portable rc scripts. -
★ Multi-instance / profile support. FreeBSD supports running several opendkim instances under different
rc.confprofiles (e.g.milteropendkim_profiles="sign verify"), each with its own socket and config. This maps directly to SCOPE.md'sresign/ multi-tenant use cases. Worth documenting as an rc.conf pattern even if we do not ship a FreeBSD rc script initially. -
Socket directory and permission creation with
install -d. FreeBSD usesinstall -d -o uid -g gid -m mode dirto atomically create the socket directory with correct ownership in a single command, rather than the commonmkdir -p; chown; chmodthree-step. Safer against TOCTOU races on tmpfs. OurRuntimeDirectory=opendkim+RuntimeDirectoryMode=0750does this atomically on systemd — the same principle. -
★
_opendkimaccount name. OpenBSD and Debian both use an underscore-prefixed (_opendkim) or unprefixed (opendkim) system account. OpenBSD convention is underscore-prefix for all system daemons to distinguish them from login accounts (_nsd,_smtpd, etc.). Our Debian package usesopendkimwithout a prefix. FreeBSD defaults tomailnull:mailnull. Adopt_opendkimif we ever ship an OpenBSD port. -
OpenBSD disables reload (
rc_reload=NO). OpenBSD's rc script has noUSR1reload — it simply restarts. Our systemd unit implementsExecReload=/bin/kill -USR1 $MAINPIDwhich is the correct behaviour for live config reload without dropping connections. Do not follow OpenBSD's simplification here. -
Privilege drop via daemon
-uflag vs. init-systemUser=. OpenBSD passes-u _opendkimon the command line; FreeBSD passes-u uid:gid. Our unit usesUser=opendkim(systemd). The daemon's own-uflag works on all platforms and is a useful fallback for deployments without systemd (e.g. Docker, manual invocation). Keep-uas a documented CLI option even on systemd deployments.
The following scripts are collected verbatim from upstream distro sources for eventual
placement in contrib/. Each is annotated with its source URL and the version of
opendkim it was written for. They will need adaptation for PhoenixDKIM paths
(/usr/sbin/opendkim, /etc/opendkim.conf, user name, socket path).
Source: https://codeberg.org/FreeBSD/freebsd-ports/raw/branch/main/mail/opendkim/files/milter-opendkim.in
Upstream version: opendkim 2.10.3
#!/bin/sh
# PROVIDE: milter-opendkim
# REQUIRE: DAEMON
# BEFORE: mail
# KEYWORD: shutdown
# Define these milteropendkim_* variables in one of these files:
# /etc/rc.conf
# /etc/rc.conf.local
# /etc/rc.conf.d/milteropendkim
#
# milteropendkim_enable (bool): Set to "NO" by default.
# Set it to "YES" to enable dkim-milter
# milteropendkim_uid (str): Set username to run milter.
# milteropendkim_gid (str): Set group to run milter.
# milteropendkim_profiles (list): Set to "" by default.
# Define your profiles here.
# milteropendkim_cfgfile (str): Configuration file. See opendkim.conf(5)
#
# milteropendkim_${profile}_* : Variables per profile.
# Sockets must be different from each other.
#
# milteropendkim_socket_perms (str):
# Permissions for local|unix socket.
#
# all parameters below now can be set in opendkim.conf(5).
# milteropendkim_socket (str): Path to the milter socket.
# milteropendkim_domain (str): Domainpart of From: in mails to sign.
# milteropendkim_key (str): Path to the private key file to sign with.
# milteropendkim_selector (str): Selector to use when signing
# milteropendkim_alg (str): Algorithm to use when signing
# milteropendkim_flags (str): Flags passed to start command.
. /etc/rc.subr
name="milteropendkim"
rcvar=milteropendkim_enable
extra_commands="reload"
start_precmd="dkim_prepcmd"
start_postcmd="dkim_start_postcmd"
stop_postcmd="dkim_postcmd"
command="%%PREFIX%%/sbin/opendkim"
_piddir="/var/run/milteropendkim"
pidfile="${_piddir}/pid"
sig_reload="USR1"
load_rc_config $name
#
# DO NOT CHANGE THESE DEFAULT VALUES HERE
#
: ${milteropendkim_enable:="NO"}
: ${milteropendkim_uid:="mailnull"}
: ${milteropendkim_gid:="mailnull"}
: ${milteropendkim_cfgfile:="%%PREFIX%%/etc/mail/opendkim.conf"}
: ${milteropendkim_socket_perms:="0755"}
# Options other than above can be set with $milteropendkim_flags.
# see dkim-milter documentation for detail.
extra_commands="reload"
start_precmd="dkim_prepcmd"
start_postcmd="dkim_start_postcmd"
stop_postcmd="dkim_cleansockets"
command="%%PREFIX%%/sbin/opendkim"
sig_reload="USR1"
dkim_cleansockets()
{
case ${milteropendkim_socket%:*} in
local|unix)
rm -f "${milteropendkim_socket#*:}"
;;
esac
}
dkim_get_pidfile()
{
if get_pidfile_from_conf PidFile ${milteropendkim_cfgfile#-x }; then
pidfile="$_pidfile_from_conf"
else
pidfile="/var/run/milteropendkim/${profile:-pid}"
fi
}
dkim_prepcmd()
{
dkim_cleansockets
dkim_get_pidfile
if [ ! -d "$(dirname "$pidfile")" ]; then
mkdir "$(dirname "$pidfile")"
fi
case ${milteropendkim_socket%:*} in
local|unix)
socketfile=${milteropendkim_socket#*:}
install -d -o ${milteropendkim_uid%:*} -g $milteropendkim_gid \
-m ${milteropendkim_socket_perms} \
${pidfile%/*} ${socketfile%/*}
;;
esac
}
dkim_start_postcmd()
{
case ${milteropendkim_socket%:*} in
local|unix)
# postcmd is executed too fast and socket is not created before checking...
sleep 1
chmod -f ${milteropendkim_socket_perms} ${milteropendkim_socket#*:}
;;
esac
}
if [ -n "$2" ]; then
profile="$2"
if [ -n "${milteropendkim_profiles}" ]; then
pidfile="${_piddir}/${profile}.pid"
eval milteropendkim_enable="\${milteropendkim_${profile}_enable:-${milteropendkim_enable}}"
eval milteropendkim_socket="\${milteropendkim_${profile}_socket:-}"
eval milteropendkim_socket_perms="\${milteropendkim_${profile}_socket_perms:-}"
if [ -z "${milteropendkim_socket}" ];then
echo "You must define a socket (milteropendkim_${profile}_socket)"
exit 1
fi
eval milteropendkim_cfgfile="\${milteropendkim_${profile}_cfgfile:-${milteropendkim_cfgfile}}"
eval milteropendkim_domain="\${milteropendkim_${profile}_domain:-${milteropendkim_domain}}"
eval milteropendkim_key="\${milteropendkim_${profile}_key:-${milteropendkim_key}}"
eval milteropendkim_selector="\${milteropendkim_${profile}_selector:-${milteropendkim_selector}}"
eval milteropendkim_alg="\${milteropendkim_${profile}_alg:-${milteropendkim_alg}}"
eval milteropendkim_flags="\${milteropendkim_${profile}_flags:-${milteropendkim_flags}}"
if [ -f "${milteropendkim_cfgfile}" ];then
milteropendkim_cfgfile="-x ${milteropendkim_cfgfile}"
else
milteropendkim_cfgfile=""
fi
if [ -n "${milteropendkim_socket}" ];then
_socket_prefix="-p"
fi
if [ -n "${milteropendkim_uid}" ];then
_uid_prefix="-u"
if [ -n "${milteropendkim_gid}" ];then
milteropendkim_uid=${milteropendkim_uid}:${milteropendkim_gid}
fi
fi
if [ -n "${milteropendkim_domain}" ];then
milteropendkim_domain="-d ${milteropendkim_domain}"
fi
if [ -n "${milteropendkim_key}" ];then
milteropendkim_key="-k ${milteropendkim_key}"
fi
if [ -n "${milteropendkim_selector}" ];then
milteropendkim_selector="-s ${milteropendkim_selector}"
fi
if [ -n "${milteropendkim_alg}" ];then
milteropendkim_alg="-S ${milteropendkim_alg}"
fi
dkim_get_pidfile
command_args="-l ${_socket_prefix} ${milteropendkim_socket} ${_uid_prefix} ${milteropendkim_uid} -P ${pidfile} ${milteropendkim_cfgfile} ${milteropendkim_domain} ${milteropendkim_key} ${milteropendkim_selector} ${milteropendkim_alg}"
else
echo "$0: extra argument ignored"
fi
else
if [ -n "${milteropendkim_profiles}" ] && [ -n "$1" ]; then
if [ "$1" != "restart" ]; then
for profile in ${milteropendkim_profiles}; do
echo "===> milteropendkim profile: ${profile}"
%%PREFIX%%/etc/rc.d/milter-opendkim $1 ${profile}
retcode="$?"
if [ "${retcode}" -ne 0 ]; then
failed="${profile} (${retcode}) ${failed:-}"
else
success="${profile} ${success:-}"
fi
done
exit 0
else
restart_precmd=""
fi
else
if [ -f "${milteropendkim_cfgfile}" ];then
milteropendkim_cfgfile="-x ${milteropendkim_cfgfile}"
else
milteropendkim_cfgfile=""
fi
if [ -n "${milteropendkim_socket}" ];then
_socket_prefix="-p"
fi
if [ -n "${milteropendkim_uid}" ];then
_uid_prefix="-u"
if [ -n "${milteropendkim_gid}" ];then
milteropendkim_uid=${milteropendkim_uid}:${milteropendkim_gid}
fi
fi
if [ -n "${milteropendkim_domain}" ];then
milteropendkim_domain="-d ${milteropendkim_domain}"
fi
if [ -n "${milteropendkim_key}" ];then
milteropendkim_key="-k ${milteropendkim_key}"
fi
if [ -n "${milteropendkim_selector}" ];then
milteropendkim_selector="-s ${milteropendkim_selector}"
fi
if [ -n "${milteropendkim_alg}" ];then
milteropendkim_alg="-S ${milteropendkim_alg}"
fi
dkim_get_pidfile
command_args="-l ${_socket_prefix} ${milteropendkim_socket} ${_uid_prefix} ${milteropendkim_uid} -P ${pidfile} ${milteropendkim_cfgfile} ${milteropendkim_domain} ${milteropendkim_key} ${milteropendkim_selector} ${milteropendkim_alg}"
fi
fi
run_rc_command "$1"Adaptation notes for PhoenixDKIM:
- Replace
%%PREFIX%%with/usr/local(FreeBSD) or the install prefix. - Default user/group: change
mailnull:mailnull→opendkim:opendkim. - Config path:
%%PREFIX%%/etc/mail/opendkim.conf→/usr/local/etc/opendkim.conf. - The
dkim_get_pidfilehelper readsPidFilefrom the config at start time — useful if the admin sets a custom pidfile path. - The profile mechanism (multiple instances via
milteropendkim_profiles) is directly useful for theResign/ multi-tenant use case in SCOPE.md.
Source: https://raw.githubusercontent.com/openbsd/ports/master/mail/opendkim/pkg/opendkim.rc
Upstream version: opendkim 2.10.3 (revision 3)
#!/bin/ksh
daemon="${TRUEPREFIX}/sbin/opendkim"
daemon_flags="-x ${SYSCONFDIR}/opendkim.conf -u _opendkim"
. /etc/rc.d/rc.subr
rc_reload=NO
rc_cmd $1Adaptation notes for PhoenixDKIM:
${TRUEPREFIX}and${SYSCONFDIR}are substituted by the OpenBSD ports framework at package-install time; for a manual install use/usr/localand/etcrespectively.- User is
_opendkim(OpenBSD convention: underscore-prefix for system daemons). rc_reload=NOdeliberately omits theUSR1reload — OpenBSD restarts instead. For PhoenixDKIM, consider enabling reload: setrc_reload=YESand addrc_reload_signal=USR1(supported in OpenBSD 7.0+).
Source: https://raw.githubusercontent.com/alpinelinux/aports/master/community/opendkim/opendkim.initd
Upstream version: opendkim as packaged in Alpine community
#!/sbin/openrc-run
owner=opendkim
pidfile=/run/opendkim/opendkim.pid
cfgfile=/etc/opendkim/opendkim.conf
command=/usr/sbin/opendkim
command_args="$command_args -u $owner -f"
command_background=yes
required_files="$cfgfile"
depend() {
need net
before mta
}
start_pre() {
local socket=$(grep ^Socket.*local: $cfgfile | cut -d: -f2)
local basedir=$(grep ^BaseDirectory $cfgfile | awk '{print $2}')
[ "${socket:0:1}" = "/" ] && checkpath -d -o $owner ${socket%/*}
[ "$basedir" ] && checkpath -d -o $owner $basedir
checkpath -d -o $owner ${pidfile%/*}
}Companion conf.d/opendkim (Alpine):
# Extra arguments to pass to command line
#command_args=""Adaptation notes for PhoenixDKIM:
- Config path matches our installed location (
/etc/opendkim/opendkim.confor/etc/opendkim.conf— adjust to whichever the package installs). start_pre()parsesSocketandBaseDirectoryfrom opendkim.conf using grep/awk to create required directories before start — this is the OpenRC idiomatic equivalent of systemd'sRuntimeDirectory=.command_background=yestells OpenRC to manage the pidfile itself; remove if opendkim writes its own pidfile (controlled by thePidFileconfig key).need net+before mtacorrectly expresses the dependency: network up, mail daemon not started yet.- The
Socketgrep is fragile (^Socket.*local:) — it missesinet:sockets and breaks if the config has leading whitespace. Consider improving the parser if adopting this script.
Source: https://raw.githubusercontent.com/void-linux/void-packages/master/srcpkgs/opendkim/files/opendkim/run
Upstream version: opendkim as packaged in Void Linux
#!/bin/sh
exec 2>&1
[ -r ./conf ] && . ./conf
exec opendkim -f ${OPTS}Companion conf file (place in the service directory, e.g. /etc/sv/opendkim/conf):
# OPTS="-x /etc/opendkim.conf -u opendkim"
OPTS="-x /etc/opendkim.conf -u opendkim"Adaptation notes for PhoenixDKIM:
-
Void Linux did not ship a
log/runscript; add one if svlogd logging is desired:#!/bin/sh exec svlogd -tt /var/log/opendkim
-
The
exec 2>&1redirect merges stderr into stdout so runit/svlogd captures all output. opendkim logs via syslog by default;-fkeeps it in the foreground without forking (required for runit supervision). -
${OPTS}must include at minimum-x /path/to/opendkim.conf. The-u opendkimprivilege drop is done on the command line here rather than in the config file. -
The
confsourcing pattern is the Void/runit convention for per-service environment variables; it is equivalent to systemdEnvironmentFile=.