The panel's signer is the only one. Gone: the opendkim package and its
configuration, the syslog-relay and opendkim programs, /dev/log and
/run/opendkim, the reload by USR1 through supervisord
(internal/supervisor/supervisor.go), internal/syslogrelay, the port of
OpenDKIM's From: parser (internal/milter/mailparse.go and its probe,
harness and test/upstream scripts), OPENDKIM_SOCKET and OPENDKIM_DIR.
Keys: internal/domain/keys.go (Keys, NewKeys, DKIM_DIR=/data/dkim) keeps
the keys and writes a selector table, /data/dkim/selectors ("<name>
<selector>"), which the signer reads in place of the KeyTable - it reads
no database, as the sender check reads none. The table is written before
the signer serves (EnsureServerSigned moved there from the notifier).
Keys and table 0600, directories 0700, the panel's. The entrypoint copies
/data/opendkim/keys once, as the panel user, into /data/dkim.new renamed
when whole, and stops the start if the copy fails; /data/opendkim is left
for a rollback to 2.7.x.
Sender check: one RFC 5322 address as a mail program reads it, held
against the bindings; the 256-byte refusal and the texts naming OpenDKIM
go. Allowed() folded the domain through strings.ToLower, which makes the
Kelvin sign a "k" - the comparison with OpenDKIM's reading had hidden it;
it folds ASCII only now.
Health: two dkim-signer rows (applications, notifications) in Milter
sockets, opendkim out of the liveness set; the card no longer takes any
row with a note for the spam filter. Texts as in the design commit.
KILL stays in deploy/docker-compose.yml: measured on the test server,
root without it cannot signal a process of another uid - supervisord
stopping the panel, Postfix's master its children. The plan's "only use
was the reload" was wrong; the comment now gives the real uses.
e2e: one signature, the panel's, verified by dkimpy; the /data/dkim modes;
the OpenDKIM log and process checks, testNeverSignedForAnother and the
cited opendkim, libopendkim11 and libmilter1.0.1 go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -155,25 +155,48 @@ Two findings while writing it: a folded header reaches a milter
|
||||
`-separated (the signer rebuilds CRLF), and go-milter calls no Abort on a
|
||||
dropped connection (a one-hour watchdog closes the signer).
|
||||
|
||||
### Stage 2 - OpenDKIM removed (no release)
|
||||
### Stage 2 - OpenDKIM removed (no release) - done
|
||||
|
||||
- [ ] Chain: OpenDKIM out of both milter lists.
|
||||
- [ ] Go: `internal/domain/opendkim.go` reduced to key storage (tables,
|
||||
- [x] Chain: OpenDKIM out of both milter lists.
|
||||
- [x] Go: `internal/domain/opendkim.go` reduced to key storage (tables,
|
||||
`Rebuild`, `assertConfigSafe`, the USR1 reload go), `internal/supervisor`
|
||||
(its only caller is the reload), `internal/syslogrelay`,
|
||||
`internal/milter/mailparse.go` and its tests and testdata, the
|
||||
sender-check texts; Resync's "OpenDKIM's tables" step; Health's
|
||||
liveness set and socket row (Q3); `OPENDKIM_SOCKET`/`OPENDKIM_DIR`.
|
||||
- [ ] Image: the `opendkim` package, `opendkim.conf`, the two supervisord
|
||||
- [x] Image: the `opendkim` package, `opendkim.conf`, the two supervisord
|
||||
programs, the `/dev/log` link and `/run/opendkim`, `usermod -aG selfpost
|
||||
opendkim`, crashexit's spared list; `deploy/docker-compose.yml`'s `KILL`
|
||||
capability (its only use was the reload).
|
||||
- [ ] Keys: `/data/opendkim/keys` -> `/data/dkim/keys` (Q2): the entrypoint
|
||||
capability (its only use was the reload) - **kept, see below**.
|
||||
- [x] Keys: `/data/opendkim/keys` -> `/data/dkim/keys` (Q2): the entrypoint
|
||||
copies the tree once and leaves the old one for a rollback to 2.7.x until
|
||||
the next release; KeyTable and SigningTable go with the new layout.
|
||||
- [ ] Tests: `test/upstream/*.sh`, e2e's OpenDKIM log and process checks,
|
||||
- [x] Tests: `test/upstream/*.sh`, e2e's OpenDKIM log and process checks,
|
||||
the 256-byte test rewritten for the new rule.
|
||||
|
||||
*Done (2026-10-16):* `internal/domain/keys.go` (`Keys`, `NewKeys`,
|
||||
`DKIM_DIR`) keeps the keys and writes a selector table,
|
||||
`/data/dkim/selectors`, a line `<name> <selector>` each, which the signer
|
||||
reads instead of the KeyTable: the signer reads no database, as the sender
|
||||
check reads none - the panel's one SQLite connection is shared with the
|
||||
pages, and a long query would hold up mail. The table is written before the
|
||||
signer serves (`EnsureServerSigned`, moved there from the notifier), so the
|
||||
first start of 2.8.0 needs nothing of the operator. Keys and table are
|
||||
0600, directories 0700, owned by the panel; the entrypoint copies the old
|
||||
keys as the panel user (`setpriv`), into `/data/dkim.new`, renamed when
|
||||
whole, and stops the start if the copy fails - else the server's name would
|
||||
get a new key. Three findings: `KILL` stays - measured on the test server,
|
||||
root without it cannot signal a process of another uid, and supervisord
|
||||
stops the panel and Postfix's master its children that way (the plan's
|
||||
"only use" was wrong); the sender check's `Allowed` took the domain through
|
||||
`strings.ToLower`, which makes the Kelvin sign a "k" - the comparison with
|
||||
OpenDKIM's reading had hidden it, it now folds ASCII only; the Milter
|
||||
sockets card told the spam filter by its row having a note, which the
|
||||
signer's rows have too. The e2e drops the OpenDKIM-only cases
|
||||
(`testNeverSignedForAnother`) and checks the one signature, the tree's
|
||||
modes and the cited packages without opendkim, libopendkim11 and
|
||||
libmilter1.0.1.
|
||||
|
||||
### Stage 3 - documents, the canary, the cut
|
||||
|
||||
- [ ] architecture § OpenDKIM -> § DKIM signing; security.md (the
|
||||
|
||||
Reference in New Issue
Block a user