panel-dkim-signing stage 2: OpenDKIM removed
test / test (push) Canceled after 0s

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:
mix
2026-10-16 01:05:39 +03:00
co-authored by Claude Opus 5.5
parent 005922bc7d
commit faa3c11ae7
96 changed files with 971 additions and 2247 deletions
+26 -7
View File
@@ -8,13 +8,32 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
### Added
- **The panel signs outgoing mail with DKIM itself** (panel-dkim-signing,
stage 1 of [the plan](docs/plans/panel-dkim-signing.md)): a milter of the
panel's on two sockets, one for applications' mail - signed with the key of
the domain the login belongs to - and one for the panel's own, signed with
the server's name. `relaxed/simple`, RFC 6376 § 5.4.1's headers and `From`
once more, as OpenDKIM signs; strict. Until OpenDKIM leaves the image both
sign every message, and the e2e suite holds the two to the same `h=` and
`bh=` and has dkimpy - an independent implementation - verify each.
[the plan](docs/plans/panel-dkim-signing.md)): a milter of the panel's on
two sockets, one for applications' mail - signed with the key of the
domain the login belongs to - and one for the panel's own, signed with the
server's name. `relaxed/simple`, RFC 6376 § 5.4.1's headers and `From`
once more, as OpenDKIM signed; strict. Before OpenDKIM left, both signed
every message on the e2e stand and agreed on `h=` and `bh=`; dkimpy - an
independent implementation - verifies the panel's signature on every run.
### Removed
- **OpenDKIM** - a 2018 beta with open 2026 CVEs and no maintainer - and what
SelfPost kept around it: the syslog relay and `/dev/log`, the reload by a
signal through supervisord, the port of OpenDKIM's `From:` parser.
Server › Health shows the signer's two sockets in its place.
### Changed
- **The DKIM keys moved to `/data/dkim`** and are the panel's alone (0600):
the first start copies them from `/data/opendkim`, which is left as it was
for a rollback to 2.7.x. Keys, selectors and DNS records do not change.
The KeyTable and SigningTable are gone; a selector table the signer reads
takes their place. `OPENDKIM_DIR` and `OPENDKIM_SOCKET` are gone.
- **The sender check reads `From:` as a mail program does** and no longer as
OpenDKIM did: the line must be one address at a domain the application
may send as, and the 256-byte limit of OpenDKIM's buffer goes. The key is
the login's, so no `From:` line can choose another tenant's.
### Fixed