base-trixie: the image on Debian trixie, Postfix 3.10.13; Received: hidden on 465/587
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
The runtime base is debian:trixie-slim, the build stage golang:1.26-trixie:
Postfix 3.10.13 with upstream's 2026 security fixes up to the August
batch, libmilter 8.18.1, OpenSSL 3.5. Every citation of another program in
code, scripts and documents was re-read against the trixie sources
(dev/upstream; bookworm's kept in dev/upstream-bookworm) and updated;
development.md's cited-package table holds the trixie versions.
What the re-reading changed in behaviour:
- logtail: reject lines with sasl_method/sasl_username/sasl_sender
(smtpd_check.c:1019-1026); cleanup's "removed (canceled)" forgets a
port-25 id (cleanup_api.c:363-364).
- internal/postfix/retry.go reads postconf's stdout only: since 3.9 a
deprecated-parameter warning on stderr made one value too many and the
panel fell back to the compiled-in retry policy.
- logrotate-loop.sh: logrotate 3.22 exits 1 when it ignores a config;
the loop refuses on that output whatever the status.
- postfix-config.sh: cyrus_sasl_config_path set explicitly (bookworm's
07_sasl_config.diff is gone); maillog_file_permissions=0640; mynetworks
explicit; Dockerfile: SYNC_CHROOT= in /etc/default/postfix,
opendkim-tools dropped, openssl named, systemd-standalone-sysusers so
cron does not bring the whole of systemd.
- The selfpost group is 10998, outside the system range 100-999: in
trixie a package took 998 and the build failed (owner's decision:
a conflict-free id, the distribution's own ids untouched). The
entrypoint hands /data back by name when the user or the group differs.
Guide, backup refusal text, help (design commit 68ec8b2), e2e.
- smtpd_hide_client_session=yes on smtps and submission (owner's
decision): Received: names no client, TLS, login or protocol; port 25
keeps the full header. e2e checks both.
- test/upstream/opendkim-probe.sh makes keys with openssl genrsa.
Tests: on the server, make e2e exit 0 (674 s, the image built on trixie),
go vet + go test 27 packages ok. CHANGELOG [Unreleased], guide,
architecture.md, security.md, roadmap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+62
-26
@@ -6,7 +6,7 @@
|
||||
# docker build -f build/Dockerfile -t selfpost:dev --build-arg VERSION=dev .
|
||||
|
||||
# ---- build stage -------------------------------------------------------------
|
||||
FROM golang:1.26-bookworm AS build
|
||||
FROM golang:1.26-trixie AS build
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
@@ -30,61 +30,95 @@ RUN go vet ./... \
|
||||
-o /out/selfpost-backup ./cmd/selfpost-backup
|
||||
|
||||
# ---- runtime stage -----------------------------------------------------------
|
||||
FROM debian:bookworm-slim AS runtime
|
||||
FROM debian:trixie-slim AS runtime
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Preseed Postfix so its install is non-interactive and yields a working
|
||||
# main.cf. The real relay configuration is generated by the panel.
|
||||
# (postfix 3.7.11-0+deb12u1, debian/templates: postfix/main_mailer_type and
|
||||
# postfix/mailname are the questions the install asks.)
|
||||
# What else arrives through Depends, and is used here: openssl, by
|
||||
# ca-certificates ("Depends: openssl (>= 1.1.1)", packages.debian.org/bookworm/
|
||||
# ca-certificates) - postfix-cert-reload.sh; python3, by supervisor (supervisor
|
||||
# 4.2.5-1, debian/control, ${python3:Depends}) - crashexit.py. sasl2-bin brings
|
||||
# saslpasswd2 and libsasl2-modules the PLAIN and LOGIN plugins; the sasldb
|
||||
# auxprop plugin is in libsasl2-modules-db, a Depends of libsasl2-2
|
||||
# (cyrus-sasl2 2.1.28+dfsg-10, debian/control and debian/*.install). db-util
|
||||
# ships /usr/bin/db_dump (packages.debian.org/bookworm/amd64/db-util/filelist).
|
||||
# (postfix 3.10.13-0+deb13u1, debian/templates:14 and :50:
|
||||
# postfix/main_mailer_type and postfix/mailname are the questions the install
|
||||
# asks; debian/postfix.postinst:156-171 writes main.cf for any answer but "No
|
||||
# configuration".)
|
||||
# openssl is named because postfix-cert-reload.sh runs it, not left to arrive
|
||||
# with ca-certificates. python3 arrives with supervisor (supervisor 4.2.5-3,
|
||||
# debian/control:29, ${python3:Depends}) - crashexit.py. sasl2-bin brings
|
||||
# saslpasswd2 (cyrus-sasl2 2.1.28+dfsg1-9, debian/rules:207,
|
||||
# debian/sasl2-bin.install:3, usr/sbin) and depends on db-util
|
||||
# (debian/control:36); libsasl2-modules brings the PLAIN and LOGIN plugins
|
||||
# (debian/libsasl2-modules.install:4 and :6); the sasldb auxprop plugin is in
|
||||
# libsasl2-modules-db (debian/libsasl2-modules-db.install:1), a Depends of
|
||||
# libsasl2-2 (debian/control:65). db-util is named for /usr/bin/db_dump, which
|
||||
# the panel runs (internal/app/sasl.go); that db-util ships that path on
|
||||
# trixie is not in a source read here - the image build and the e2e sasldb
|
||||
# test say whether it does.
|
||||
# opendkim-tools is not installed: nothing in the image runs its programs
|
||||
# (DKIM keys are made in Go, internal/domain/dkim.go).
|
||||
# systemd-standalone-sysusers is named so that cron-daemon-common, which
|
||||
# logrotate brings (logrotate 3.22.0-1, debian/control: "Depends: cron |
|
||||
# anacron | cron-daemon | systemd-sysv"), creates its group with it rather
|
||||
# than with the whole of systemd, the first alternative of its "Depends:
|
||||
# systemd | systemd-standalone-sysusers | systemd-sysusers" (dpkg -s in the
|
||||
# image, 2026-10-15). Nothing here runs systemd.
|
||||
RUN echo "postfix postfix/mailname string localhost" | debconf-set-selections \
|
||||
&& echo "postfix postfix/main_mailer_type string Internet Site" | debconf-set-selections \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
postfix \
|
||||
opendkim \
|
||||
opendkim-tools \
|
||||
sasl2-bin \
|
||||
libsasl2-modules \
|
||||
db-util \
|
||||
supervisor \
|
||||
logrotate \
|
||||
ca-certificates \
|
||||
openssl \
|
||||
curl \
|
||||
systemd-standalone-sysusers \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Unprivileged user for the panel process.
|
||||
# Debian's postfix runs its chroot sync on every "postfix check" and "postfix
|
||||
# start-fg" (postfix 3.10.13-0+deb13u1, debian/patches/
|
||||
# debian-run-configure-instance-from-create-missing.patch); with no service
|
||||
# chrooted (build/postfix-config.sh) it would only copy /etc/resolv.conf and
|
||||
# the like into the queue under /data on each start. SYNC_CHROOT empty turns
|
||||
# it off (debian/configure-instance.in:22-24 and :44; debian/README.Debian:136-138).
|
||||
RUN printf 'SYNC_CHROOT=\n' > /etc/default/postfix
|
||||
|
||||
# Unprivileged user for the panel process. Its ids are left to useradd: the
|
||||
# entrypoint gives /data back to it by name on every start, so a number
|
||||
# that differs from one image to the next changes nothing.
|
||||
RUN useradd --system --no-create-home --shell /usr/sbin/nologin panel
|
||||
|
||||
# Shared group bridging the unprivileged services: the panel generates
|
||||
# per-domain DKIM keys, application SASL accounts (sasldb2) and the Postfix
|
||||
# sender map, while OpenDKIM and Postfix (different users) must read them.
|
||||
# Membership in this group — plus setgid dirs under /data (set up in
|
||||
# entrypoint.sh) — lets OpenDKIM read the panel-owned keys and lets Postfix read
|
||||
# the sasldb2/sender map. (The supervisor control socket has a group of its
|
||||
# own, `supervisor`, below.)
|
||||
# The id is fixed, and it is the one the group has always had: an operator
|
||||
# gives the TLS private key on the host to this group by number, so that the
|
||||
# panel can put it into a full backup (guide § Taking a full backup).
|
||||
# groupadd(8) refuses a --gid already in use, so a package that took 998 would
|
||||
# Membership in this group - plus setgid dirs under /data (set up in
|
||||
# entrypoint.sh) - lets OpenDKIM read the panel-owned keys and lets Postfix
|
||||
# read the sasldb2/sender map. (The supervisor control socket has a group of
|
||||
# its own, `supervisor`, below.)
|
||||
# The id is fixed, because the host sees it: an operator gives the TLS
|
||||
# private key on the host to this group by number, so that the panel can put
|
||||
# it into a full backup (guide § Taking a full backup). It lies outside the
|
||||
# range the distribution hands out to system groups, 100-999 (adduser 3.152,
|
||||
# /etc/adduser.conf: "Default: FIRST_SYSTEM_GID=100, LAST_SYSTEM_GID=999";
|
||||
# passwd 1:4.17.4-2, /etc/login.defs: SYS_GID_MIN 101, SYS_GID_MAX 999 - both
|
||||
# read in the image, 2026-10-15), so no package can take it, and far above
|
||||
# the 1000 a host starts its users' groups at, so a host is unlikely to have
|
||||
# a group of that number that would read the key too. Until 2.7.0 it was
|
||||
# 998, inside that range: in the trixie image systemd took 998 for
|
||||
# systemd-network and the build failed, and on the test server's host 998
|
||||
# is systemd-network too (seen 2026-10-15).
|
||||
# groupadd(8) refuses a --gid already in use, so an id taken after all would
|
||||
# fail this build rather than share the group.
|
||||
RUN groupadd --system --gid 998 selfpost \
|
||||
RUN groupadd --system --gid 10998 selfpost \
|
||||
&& usermod -aG selfpost panel \
|
||||
&& usermod -aG selfpost opendkim \
|
||||
&& usermod -aG selfpost postfix
|
||||
|
||||
# The panel reads the mail queue with `postqueue -p` (and the status page's
|
||||
# queue card). postqueue is setgid postdrop, which normally gives it the group
|
||||
# needed to reach Postfix's showq socket — but the documented deployment runs
|
||||
# needed to reach Postfix's showq socket - but the documented deployment runs
|
||||
# with `no-new-privileges`, which disables setgid transitions, so the panel
|
||||
# would always see "Permission denied". Making `panel` a real member of postdrop
|
||||
# grants the same access without relying on a setgid escalation the hardening
|
||||
@@ -93,8 +127,10 @@ RUN groupadd --system --gid 998 selfpost \
|
||||
# to write the maildrop directory (internal/notify/mailer.go). It does not let
|
||||
# the panel bypass any Postfix restriction that a local user does not already
|
||||
# have through the world-executable sendmail.
|
||||
# (Postfix 3.7.11, conf/postfix-files: postdrop and postqueue are
|
||||
# root:$setgid_group 2755. Linux, Documentation/userspace-api/no_new_privs.rst:
|
||||
# (Postfix 3.10.13, conf/postfix-files:140-141: postdrop and postqueue are
|
||||
# root:$setgid_group 2755; Debian sets them root:postdrop 02555, postfix
|
||||
# 3.10.13-0+deb13u1, debian/postfix.postinst:134-141. Linux,
|
||||
# Documentation/userspace-api/no_new_privs.rst:
|
||||
# with no_new_privs, execve() no longer changes the gid for a setgid file.)
|
||||
RUN usermod -aG postdrop panel
|
||||
# The supervisord control socket's group (supervisord.conf, [unix_http_server]):
|
||||
|
||||
Reference in New Issue
Block a user