release: 2.15.0: server-dmarc-hint, upstream-tls-verify
test / test (push) Canceled after 0s

The server's own name gets a DMARC record on Settings and Health, and an
inbound domain's upstream a Verified TLS mode (Postfix secure, with
Debian's CA bundle). Migration 0014; schema 14. The pins (compose, README,
guide), the guide's backup example, the planned cuts and the two roadmap
rows. No tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-18 10:28:24 +03:00
co-authored by Claude Opus 5.5
parent 6b4106f60e
commit f20c942d64
6 changed files with 17 additions and 11 deletions
+5
View File
@@ -5,6 +5,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
## [Unreleased] ## [Unreleased]
## [2.15.0] - 2026-10-18
The two proposals the security audit left as product choices. Migration
0014; schema 14.
### Added ### Added
- **Verified TLS to an inbound domain's upstream** (upstream-tls-verify; the - **Verified TLS to an inbound domain's upstream** (upstream-tls-verify; the
+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.14.5 \ > docker build -f build/Dockerfile --build-arg VERSION=2.15.0 \
> -t ghcr.io/mixeme/selfpost:2.14.5 . > -t ghcr.io/mixeme/selfpost:2.15.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.14.5 ghcr.io/mixeme/selfpost:2.15.0
``` ```
This trial runs with Docker's default capabilities and no This trial runs with Docker's default capabilities and no
+1 -1
View File
@@ -23,7 +23,7 @@
services: services:
selfpost: selfpost:
image: ghcr.io/mixeme/selfpost:2.14.5 image: ghcr.io/mixeme/selfpost:2.15.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}"
+2 -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.14.5`; adjust if semver changes mid-track): **Planned version cuts** (from pin `2.15.0`; adjust if semver changes mid-track):
| Stage | ID | Cut | | Stage | ID | Cut |
|---|---|---| |---|---|---|
@@ -157,6 +157,7 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
| 44 | label-tag | `2.14.3` | | 44 | label-tag | `2.14.3` |
| 45 | security-audit-2026-10-17, stages 0-6 | `2.14.4` | | 45 | security-audit-2026-10-17, stages 0-6 | `2.14.4` |
| 46 | etrn-silent | `2.14.5` | | 46 | etrn-silent | `2.14.5` |
| 47 | server-dmarc-hint, upstream-tls-verify | `2.15.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
@@ -218,14 +218,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.14.5`. **No 2.x image is deliberately never `:latest`. The current pin is `2.15.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.14.5 \ docker build -f build/Dockerfile --build-arg VERSION=2.15.0 \
-t ghcr.io/mixeme/selfpost:2.14.5 . -t ghcr.io/mixeme/selfpost:2.15.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
@@ -1073,7 +1073,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.14.4 but this image is 2.14.5 — restore into the matching image (selfpost:2.14.4) backup: this backup was created by SelfPost 2.14.5 but this image is 2.15.0 — restore into the matching image (selfpost:2.14.5)
``` ```
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
+2 -2
View File
@@ -29,8 +29,8 @@ in `git log` and [CHANGELOG.md](../CHANGELOG.md).
| ID | Topic | Status | Progress | Plan | | ID | Topic | Status | Progress | Plan |
|---|---|---|---|---| |---|---|---|---|---|
| security-audit-2026-10-17 | Follow-ups of the 2026-10-17 security audit: A2 (high), seven mediums, the lows | stages 0-6 shipped `2.14.4` (2026-10-17); stage H (the host, S1-S3, S5) the owner's | 27/29 | [security-audit-2026-10-17.md](security-audit-2026-10-17.md) | | security-audit-2026-10-17 | Follow-ups of the 2026-10-17 security audit: A2 (high), seven mediums, the lows | stages 0-6 shipped `2.14.4` (2026-10-17); stage H (the host, S1-S3, S5) the owner's | 27/29 | [security-audit-2026-10-17.md](security-audit-2026-10-17.md) |
| upstream-tls-verify | Inbound: offer "Verified" TLS to the upstream (Postfix `secure`, the upstream's name checked), beside Required, which checks no certificate (audit M7) | built 2026-10-18 (owner: "Оба предложения делаем") | — | — | | upstream-tls-verify | Inbound: offer "Verified" TLS to the upstream (Postfix `secure`, the upstream's name checked), beside Required, which checks no certificate (audit M7) | shipped `2.15.0` | — | — |
| server-dmarc-hint | Server › Settings lists a DMARC record for the server's own name beside its DKIM and SPF (audit S3, product side) | built 2026-10-18 (owner: "Оба предложения делаем") | — | — | | server-dmarc-hint | Server › Settings lists a DMARC record for the server's own name beside its DKIM and SPF (audit S3, product side) | shipped `2.15.0` | — | — |
| inbound-upstream-result | Inbound › Log shows what the upstream answered: sent, deferred, bounced, with its last reply | shipped `2.10.0` | 7/7 | [plans/inbound-upstream-result.md](plans/inbound-upstream-result.md) | | inbound-upstream-result | Inbound › Log shows what the upstream answered: sent, deferred, bounced, with its last reply | shipped `2.10.0` | 7/7 | [plans/inbound-upstream-result.md](plans/inbound-upstream-result.md) |
| health-setup-checks | Server › Health also checks the certificate's name, Postfix's greeting and the trusted proxy (was preflight) | shipped `2.11.0` | — | — | | health-setup-checks | Server › Health also checks the certificate's name, Postfix's greeting and the trusted proxy (was preflight) | shipped `2.11.0` | — | — |
| test-email | Send a test message from the panel (was preflight) | shipped `2.12.0` | — | — | | test-email | Send a test message from the panel (was preflight) | shipped `2.12.0` | — | — |