release: 2.7.0: base-trixie - Debian trixie, Postfix 3.10.13

Cut without asking, as the owner said on 2026-10-15.

The image runs debian:trixie-slim with Postfix 3.10.13, libmilter
8.18.1, OpenSSL 3.5; every citation re-read against the trixie sources.
smtpd_hide_client_session=yes on 465/587 (owner's decision). The
selfpost group is 10998 and the panel 10999:10999, outside the system
range; the entrypoint re-owns /data by name. The panel's database is
0600; the entrypoint removes symbolic links the panel could leave under
/data. Commits 68ec8b2, 1c6e04b, a3050af.

Rolled out to the test server as 2.6.1-post.a3050af (the same code),
2026-10-15 17:07 UTC: healthy, every program RUNNING, no restarts, three
messages sent, the queue empty, no warning but outside password guessing.
The canary: one message from an application through 465 to Gmail, Yandex
and the test mailbox - Received: in the short form everywhere; Gmail
dkim=pass spf=pass dmarc=pass; Yandex spf=pass dkim=pass, not spam.
No migration, schema 11.

CHANGELOG cut; pin 2.7.0 in deploy/docker-compose.yml, README, guide (and
its sample restore message); development.md "from pin" and the rows of
base-trixie and panel-dkim-signing; roadmap row and recommended order.
No tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-15 23:14:14 +03:00
co-authored by Claude Opus 5.5
parent a27f8332ab
commit a556a13f67
6 changed files with 23 additions and 12 deletions
+9
View File
@@ -5,6 +5,15 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
## [Unreleased] ## [Unreleased]
## [2.7.0] - 2026-10-15
The image runs Debian trixie and Postfix 3.10.13, with upstream's 2026
security fixes that bookworm will not get. The `Received:` header no
longer shows where an application runs. The container's `selfpost` group
is 10998 and the panel user 10999: **on upgrade, `chgrp 10998` the TLS
private key in `certs/` on the host** (a certbot deploy hook too). The
panel's database is the panel's alone. No migration; schema 11.
### Security ### Security
- **The panel's database was readable by every user of the container.** - **The panel's database was readable by every user of the container.**
+3 -3
View File
@@ -112,8 +112,8 @@ outbound mail will not reach the real internet without DNS, PTR, and port 25.
> local image and pulls nothing: > local image and pulls nothing:
> >
> ```sh > ```sh
> docker build -f build/Dockerfile --build-arg VERSION=2.6.1 \ > docker build -f build/Dockerfile --build-arg VERSION=2.7.0 \
> -t ghcr.io/mixeme/selfpost:2.6.1 . > -t ghcr.io/mixeme/selfpost:2.7.0 .
> ``` > ```
```sh ```sh
@@ -122,7 +122,7 @@ docker run --rm -d --name selfpost-try \
-e SELFPOST_HOSTNAME=mail.local.test \ -e SELFPOST_HOSTNAME=mail.local.test \
-e PANEL_COOKIE_SECURE=false \ -e PANEL_COOKIE_SECURE=false \
-v selfpost-try-data:/data \ -v selfpost-try-data:/data \
ghcr.io/mixeme/selfpost:2.6.1 ghcr.io/mixeme/selfpost:2.7.0
``` ```
**Get the setup URL** (pick one): **Get the setup URL** (pick one):
+1 -1
View File
@@ -23,7 +23,7 @@
services: services:
selfpost: selfpost:
image: ghcr.io/mixeme/selfpost:2.6.1 image: ghcr.io/mixeme/selfpost:2.7.0
restart: unless-stopped restart: unless-stopped
environment: environment:
SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}" SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}"
+3 -1
View File
@@ -107,7 +107,7 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see 2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see
[§ Release image](#release-image)). [§ Release image](#release-image)).
**Planned version cuts** (from pin `2.6.1`; adjust if semver changes mid-track): **Planned version cuts** (from pin `2.7.0`; adjust if semver changes mid-track):
| Stage | ID | Cut | | Stage | ID | Cut |
|---|---|---| |---|---|---|
@@ -138,6 +138,8 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
| 25 | audit-2026-10-12 stage 4: panel behaviour | `2.5.4` | | 25 | audit-2026-10-12 stage 4: panel behaviour | `2.5.4` |
| 26 | audit-2026-10-12 stage 5: image and Postfix hardening | `2.6.0` | | 26 | audit-2026-10-12 stage 5: image and Postfix hardening | `2.6.0` |
| 27 | port25-bare-newline | `2.6.1` (PATCH) | | 27 | port25-bare-newline | `2.6.1` (PATCH) |
| 28 | base-trixie | `2.7.0` |
| 29 | panel-dkim-signing | `2.8.0` |
Docs-only prep (checklists in plans, no product code) uses the same per-step Docs-only prep (checklists in plans, no product code) uses the same per-step
commit rule but **no** version cut until the next product stage ships. commit rule but **no** version cut until the next product stage ships.
+4 -4
View File
@@ -204,14 +204,14 @@ cat ./data/setup-token
#### Fixed image tag #### Fixed image tag
`deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`), `deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`),
deliberately never `:latest`. The current pin is `2.6.1`. **No 2.x image is deliberately never `:latest`. The current pin is `2.7.0`. **No 2.x image is
published on ghcr.io yet** (the newest there is `1.3.0`); until one is, build published on ghcr.io yet** (the newest there is `1.3.0`); until one is, build
it from the checkout under the pinned name, and Compose uses the local image it from the checkout under the pinned name, and Compose uses the local image
instead of pulling: instead of pulling:
```sh ```sh
docker build -f build/Dockerfile --build-arg VERSION=2.6.1 \ docker build -f build/Dockerfile --build-arg VERSION=2.7.0 \
-t ghcr.io/mixeme/selfpost:2.6.1 . -t ghcr.io/mixeme/selfpost:2.7.0 .
``` ```
`VERSION` must equal the tag: it is the version the backup check compares `VERSION` must equal the tag: it is the version the backup check compares
@@ -874,7 +874,7 @@ A version mismatch at step 5 refuses to start and leaves `/data` untouched —
the panel exits with a message naming the tag to use, e.g.: the panel exits with a message naming the tag to use, e.g.:
``` ```
backup: this backup was created by SelfPost 2.6.0 but this image is 2.6.1 — restore into the matching image (selfpost:2.6.0) backup: this backup was created by SelfPost 2.6.1 but this image is 2.7.0 — restore into the matching image (selfpost:2.6.1)
``` ```
Fix the tag in `docker-compose.yml` (build that tag as under [Fixed image Fix the tag in `docker-compose.yml` (build that tag as under [Fixed image
+3 -3
View File
@@ -43,7 +43,7 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
| dns-record-collapse | A DNS record that is right is shown folded: its name and its tag, the values on request | agreed (2026-10-15) | — | — | | dns-record-collapse | A DNS record that is right is shown folded: its name and its tag, the values on request | agreed (2026-10-15) | — | — |
| own-mta-builds | Analysis: build Postfix and OpenDKIM ourselves, patched, instead of Debian's packages | analysed 2026-10-15: no own builds; three rows proposed instead | — | [own-mta-builds-2026-10-15.md](own-mta-builds-2026-10-15.md) | | own-mta-builds | Analysis: build Postfix and OpenDKIM ourselves, patched, instead of Debian's packages | analysed 2026-10-15: no own builds; three rows proposed instead | — | [own-mta-builds-2026-10-15.md](own-mta-builds-2026-10-15.md) |
| port25-bare-newline | The inbound relay's port 25 refuses bare newlines in DATA (`smtpd_forbid_bare_newline=normalize`) | shipped `2.6.1` | — | — | | port25-bare-newline | The inbound relay's port 25 refuses bare newlines in DATA (`smtpd_forbid_bare_newline=normalize`) | shipped `2.6.1` | — | — |
| base-trixie | The image's base from Debian bookworm (LTS since 2026-07-12) to trixie: Postfix 3.10 with the 2026 security batches | agreed (2026-10-15; after port25-bare-newline, MINOR) | — | — | | base-trixie | The image's base from Debian bookworm (LTS since 2026-07-12) to trixie: Postfix 3.10 with the 2026 security batches | shipped `2.7.0` | — | — |
| panel-dkim-signing | DKIM signing in the panel's own milter; OpenDKIM, the syslog relay and the parser port removed | agreed (2026-10-15; after base-trixie, MINOR); plan drafted, three questions open | 0/14 | [plans/panel-dkim-signing.md](plans/panel-dkim-signing.md) | | panel-dkim-signing | DKIM signing in the panel's own milter; OpenDKIM, the syslog relay and the parser port removed | agreed (2026-10-15; after base-trixie, MINOR); plan drafted, three questions open | 0/14 | [plans/panel-dkim-signing.md](plans/panel-dkim-signing.md) |
| phone-desktop-mode | A phone browser in "desktop site" mode gets the phone navigation | agreed (2026-10-13: after stages 1 and 2 of audit-2026-10-12) | — | — | | phone-desktop-mode | A phone browser in "desktop site" mode gets the phone navigation | agreed (2026-10-13: after stages 1 and 2 of audit-2026-10-12) | — | — |
| from-header-binding | Hold a message's `From:` header against the application that sends it | shipped `2.4.0` | 9/9 | [plans/from-header-binding.md](plans/from-header-binding.md) | | from-header-binding | Hold a message's `From:` header against the application that sends it | shipped `2.4.0` | 9/9 | [plans/from-header-binding.md](plans/from-header-binding.md) |
@@ -62,8 +62,8 @@ stages 1 and 2 as `2.5.0` the same day, stage 2b as `2.5.1`, stage 2c as
`2.5.2` (2026-10-15), and stages 3, 4 and 5 as `2.5.3`, `2.5.4` and `2.5.2` (2026-10-15), and stages 3, 4 and 5 as `2.5.3`, `2.5.4` and
`2.6.0` the same day; stage 6 (documents and tests, no cut) closed the `2.6.0` the same day; stage 6 (documents and tests, no cut) closed the
audit. Of the three rows from [own-mta-builds](#own-mta-builds), audit. Of the three rows from [own-mta-builds](#own-mta-builds),
**port25-bare-newline** shipped as `2.6.1` the same day; base-trixie and **port25-bare-newline** shipped as `2.6.1` the same day and
panel-dkim-signing follow in that order. What is agreed after it is marked so in the index; every other **base-trixie** as `2.7.0`; panel-dkim-signing follows. What is agreed after it is marked so in the index; every other
remaining item is a candidate. panel-docs shipped in remaining item is a candidate. panel-docs shipped in
[CHANGELOG.md](../CHANGELOG.md) `[1.8.0]`; dmarc-reports in `[1.7.0]` [CHANGELOG.md](../CHANGELOG.md) `[1.8.0]`; dmarc-reports in `[1.7.0]`
(its ingest path first ran in `2.0.0` and was reviewed on 2026-10-11, see (its ingest path first ran in `2.0.0` and was reviewed on 2026-10-11, see