Review pass over `1.4.0`…`1.9.1`: port 25 no longer shares the submission milter chain, DMARC reports are validated before they are stored, and the auto rate limit is correct for a non-default level-1 window. Schema migration `0010` (index only). Upgrading is a tag bump. Added: - SQLite migration `0010_send_log_app_login_index.sql` — - DMARC aggregate reports are accepted as **zip** as well as gzip or plain XML - e2e: `checkPort25ConfigCombinations` regenerates the Postfix configuration Changed: - README hero line and a **Positioning** block in `docs/product.md` record the Fixed: - The setup account's password is hashed at bcrypt cost `12` like every other - Login/setup rate limiter: protecting blocked buckets from eviction is now - `postqueue -p` output is bounded to 4 MiB (the timeout alone left the size of - [schema-migrations.md](docs/schema-migrations.md): the schema section was - postqueue reader is now time-bounded: `postqueue -p` runs under a 5-second … (11 more in CHANGELOG) Changed: - [roadmap.md](docs/roadmap.md) now carries everything the 2026-08-19 code - Extracted `internal/configsafe` — the empty-value and forbidden-character - Build, deploy and migration comments no longer cite the archived - Dropped the `parseDomainRateLimitForm` / `parseAppRateLimitForm` pass-through - Extracted shared helpers: `internal/atomicfile` (atomic temp-write+rename) and … (7 more in CHANGELOG) Removed: - Unused legacy asset `docs/assets/icon.png` (superseded by the four brand SVGs - Plan documents for already-shipped features: `domain-stats-auto-ratelimit`, Full detail: CHANGELOG.md (1.9.2).
3.0 KiB
Plan: preflight (installation check page)
Status: candidate
Date: 2026-08-19
Version: 1.x MINOR; candidate until explicitly agreed.
Goal
A dedicated /preflight page (global-admin only) that runs infrastructure-level
checks and helps the administrator confirm the instance is fully configured and
ready to deliver mail. Each failed check shows an actionable recommendation
(what to do or where to look).
Mockup
preflight, under the design
contract of panel-redesign.md: Server › Preflight,
path /server/preflight once the routes are renamed.
Scope
In:
- rDNS / PTR verification (reuse
dnscheck.Checker.checkServer) - TLS certificate validity + hostname match (CN/SAN contains
SELFPOST_HOSTNAME) - Port connectivity: 25, 465, and 587 (if
SUBMISSION_ENABLE) — dial own public IP from inside the container, expect a 220 banner - HELO/EHLO banner — connect to localhost:25, verify Postfix announces
SELFPOST_HOSTNAME(notlocalhostor a container ID) - Trusted proxy headers:
- If
TRUSTED_PROXY_CIDRset: verify peer IP is in range andX-Forwarded-Foris present - If
PANEL_COOKIE_SECURE=true: verifyX-Forwarded-Proto: https - If
TRUSTED_PROXY_CIDRempty: informational warning (panel exposed directly)
- If
- DKIM signing — OpenDKIM milter socket reachable (reuse
health.CheckSocket) - Send test email — admin enters recipient address, system sends via localhost:25, shows queued/error result
Out:
- Per-domain DNS checks (SPF, DKIM TXT, DMARC) — those live on domain detail pages.
- Delivery tracking of test email (only confirms local MTA accepted).
Done when
An administrator can open /preflight, see a traffic-light summary of all
infrastructure prerequisites, read specific fix instructions for any failures,
and send a test email to verify end-to-end flow.
Risks
- Port-connectivity check from inside the container may not reflect external reachability if NAT hairpin is unsupported (document limitation).
- Test email requires at least one configured domain (or falls back to
postmaster@SELFPOST_HOSTNAME).
Implementation checklist
Target version cut: TBD (MINOR). One commit per step; code only after roadmap status is agreed. See development.md § Plan checklists.
- Port-connectivity helper (
internal/health/port.go) — dial own IP, read SMTP banner — Sonnet - HELO banner check (connect localhost:25, parse 220 line) — Sonnet
- Hostname-in-certificate check (extend or wrap
health.CheckCertificate) — Sonnet - Handler
handlers_preflight.go(assemble all checks, actionable recommendations) — Sonnet - Test-email handler (
POST /preflight/test-email,net/smtpto localhost:25) — Sonnet - Template
preflight.html(traffic-light cards + test-email form) — Sonnet - Routes in
web.go, nav link — Sonnet