M6: network and DNS plan for hosted mail on the QNAP
Hosting decided (spec App. D §D.1 option A): Stalwart on the QNAP, receiving and sending directly; addresses @ultimo.email; mail apps allowed with app passwords; mail host mail.ultimo.email. docs/mail-server-network.md records the connection checks (clean IP, outbound 25 open, generic reverse DNS to change), the router / Synology / QNAP port layout, container ports, TLS certificate, the DNS records to set at home.pl, moving mail from home.pl, and checks after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
# Hosted mail (M6): network and DNS plan
|
||||||
|
|
||||||
|
Notes for switching `ultimo.email` mail from home.pl to Ultimo's own mail server
|
||||||
|
(Stalwart on the QNAP). Companion to the M6 plan in
|
||||||
|
`webmail-client-spec_v1.5.md` Appendix D. Gathered 2026-10-09/10.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
| | Decision |
|
||||||
|
|---|---|
|
||||||
|
| Hosting | **Everything on the QNAP** — receive and send directly (spec §D.1 option A). A relay (home.pl SMTP, SMTP2GO, Brevo) is optional, as a fallback only. |
|
||||||
|
| Domain | Addresses `name@ultimo.email`; webmail stays at `https://ultimo.email`. |
|
||||||
|
| Mail apps | **Allowed**: Thunderbird and phone mail apps use the mailboxes over IMAP/SMTP, signing in with **app passwords** (required when 2FA is on). |
|
||||||
|
| Mail host name | **`mail.ultimo.email`** (recommended; `ultimo.email` would also work, see below). |
|
||||||
|
|
||||||
|
## Current setup
|
||||||
|
|
||||||
|
- Static public IP **`178.219.143.96`** (ISP: Multiplay).
|
||||||
|
- Traffic → **router** → **Synology DSM** → DSM **reverse proxy** → **QNAP** (the webmail).
|
||||||
|
- All DNS records are at **home.pl**:
|
||||||
|
- A `ultimo.email` → `178.219.143.96` (the QNAP, through the Synology);
|
||||||
|
- MX `ultimo.email` → `serwer2295308.home.pl` — **mail is still at home.pl**;
|
||||||
|
- other records also point at home.pl.
|
||||||
|
|
||||||
|
## Checks of the connection (2026-10-10)
|
||||||
|
|
||||||
|
| Check | Result |
|
||||||
|
|---|---|
|
||||||
|
| Blocklists — Spamhaus ZEN (incl. PBL), Barracuda, SpamCop, SORBS, UCEPROTECT | **Not listed** |
|
||||||
|
| Outbound port 25 (tested on the QNAP) | **Open** |
|
||||||
|
| Reverse DNS of `178.219.143.96` | `pub-143.96.multiplay.pl` — generic: **must change** (below) |
|
||||||
|
| Inbound 25 / 465 / 587 / 993 from outside | Time out — expected: not forwarded yet, nothing listening. Re-test after setup. |
|
||||||
|
| Inbound 443 | Open (webmail) |
|
||||||
|
|
||||||
|
## To do before switching
|
||||||
|
|
||||||
|
### 1. Reverse DNS (ask Multiplay)
|
||||||
|
|
||||||
|
Set the reverse DNS (PTR) of `178.219.143.96` to **`mail.ultimo.email`**.
|
||||||
|
|
||||||
|
Why: receiving servers (Gmail, Outlook…) check that three things agree — the
|
||||||
|
IP's reverse DNS name, that name's A record pointing back to the IP, and the
|
||||||
|
name the mail server introduces itself with (its SMTP greeting). A generic ISP
|
||||||
|
name or a mismatch reads as a hijacked home computer and hurts delivery.
|
||||||
|
`ultimo.email` itself would work too (its A record already points here); a
|
||||||
|
separate `mail.` name keeps mail working if the website ever moves elsewhere.
|
||||||
|
|
||||||
|
### 2. Router: forward the mail ports straight to the QNAP
|
||||||
|
|
||||||
|
DSM's reverse proxy carries only web traffic (HTTP/HTTPS); SMTP and IMAP are
|
||||||
|
other protocols, so these ports go from the router directly to the QNAP:
|
||||||
|
|
||||||
|
| Outside port | To | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| 443, 80 | Synology (as today) | webmail, CalDAV/CardDAV (`/dav/`, `/.well-known/…`), certificates |
|
||||||
|
| **25** | QNAP | receiving mail from other servers (must be 25: MX delivery always uses it) |
|
||||||
|
| **465** | QNAP | sending from mail apps (SMTP over TLS) |
|
||||||
|
| **587** | QNAP | sending from mail apps (SMTP + STARTTLS) |
|
||||||
|
| **993** | QNAP | mail apps reading mail (IMAP over TLS) |
|
||||||
|
|
||||||
|
Mail sent by the QNAP leaves through the same router, i.e. from
|
||||||
|
`178.219.143.96` — the address the reverse DNS names.
|
||||||
|
|
||||||
|
### 3. The container's ports
|
||||||
|
|
||||||
|
Stalwart listens inside its container on the standard ports; Docker publishes
|
||||||
|
them on the QNAP — the same numbers if free (`"25:25"`, `"465:465"`, `"587:587"`,
|
||||||
|
`"993:993"`), or any free QNAP port (e.g. `"2525:25"`) with the router mapping
|
||||||
|
the standard outside port to it. Outside ports stay standard: 25 is mandatory,
|
||||||
|
and mail apps assume 465/587/993 when setting up an account.
|
||||||
|
|
||||||
|
Verify after setup: Stalwart must see the **real IP** of connecting servers and
|
||||||
|
apps (not a Docker address) — its spam checks and sign-in throttling use it.
|
||||||
|
|
||||||
|
### 4. TLS certificate for the mail server
|
||||||
|
|
||||||
|
The Synology holds the HTTPS certificate, but IMAP/SMTP connections end at the
|
||||||
|
QNAP, so Stalwart needs its own for `mail.ultimo.email`. Options:
|
||||||
|
|
||||||
|
- **(recommended)** Stalwart's own Let's Encrypt certificate: Let's Encrypt
|
||||||
|
checks over port 80, which goes to the Synology — add a **DSM reverse-proxy
|
||||||
|
rule: host `mail.ultimo.email`, port 80 → QNAP, Stalwart's HTTP port**.
|
||||||
|
Renews itself.
|
||||||
|
- DNS-based check, if home.pl's DNS can be updated automatically.
|
||||||
|
- Copy the Synology's certificate to the QNAP after every renewal (clumsiest).
|
||||||
|
|
||||||
|
### 5. DNS records at home.pl (at switch-over)
|
||||||
|
|
||||||
|
Lower the TTLs a day before.
|
||||||
|
|
||||||
|
| Record | Value |
|
||||||
|
|---|---|
|
||||||
|
| A `mail.ultimo.email` | `178.219.143.96` |
|
||||||
|
| MX `ultimo.email` | `10 mail.ultimo.email.` (replaces `serwer2295308.home.pl`) |
|
||||||
|
| TXT `ultimo.email` (SPF) | `v=spf1 mx -all` (add the relay's include if one is used) |
|
||||||
|
| TXT `<selector>._domainkey.ultimo.email` (DKIM) | the public key Stalwart generates |
|
||||||
|
| TXT `_dmarc.ultimo.email` | `v=DMARC1; p=none; rua=mailto:postmaster@ultimo.email` — watch the reports, then move to `quarantine` / `reject` |
|
||||||
|
| (optional) `autoconfig` / SRV records | so Thunderbird and phones find the server settings by themselves |
|
||||||
|
| (optional) MTA-STS, TLS-RPT | enforce encrypted delivery to us |
|
||||||
|
|
||||||
|
### 6. Moving the existing mail from home.pl
|
||||||
|
|
||||||
|
1. Create the mailboxes in Ultimo.
|
||||||
|
2. Copy each home.pl mailbox into its new one over IMAP.
|
||||||
|
3. Switch the MX.
|
||||||
|
4. Keep the home.pl account in the webmail for a while to catch mail that
|
||||||
|
still arrives there (DNS caches), then remove it.
|
||||||
|
|
||||||
|
### 7. Checks after switching
|
||||||
|
|
||||||
|
- From outside: ports 25 / 465 / 587 / 993 answer (with a TLS certificate for
|
||||||
|
`mail.ultimo.email`).
|
||||||
|
- Reverse DNS → `mail.ultimo.email` → `178.219.143.96`, and Stalwart greets as
|
||||||
|
`mail.ultimo.email`.
|
||||||
|
- Mail to and from Gmail and Outlook: headers show SPF, DKIM and DMARC **pass**,
|
||||||
|
delivered to the inbox (not spam).
|
||||||
|
- Thunderbird sets up an account with just the address and an app password.
|
||||||
@@ -843,6 +843,8 @@ Receiving needs inbound port 25, an MX record and a fixed address; many home ISP
|
|||||||
| **B. NAS + relay (recommended)** | Small VPS holds the MX, forwards to the NAS over WireGuard | Relay service (SMTP2GO / Postmark / SES) or the VPS | Mail stays on the NAS; reliable delivery; the VPS is the SMTP-time spam edge (§C.7). |
|
| **B. NAS + relay (recommended)** | Small VPS holds the MX, forwards to the NAS over WireGuard | Relay service (SMTP2GO / Postmark / SES) or the VPS | Mail stays on the NAS; reliable delivery; the VPS is the SMTP-time spam edge (§C.7). |
|
||||||
| **C. Stalwart on a VPS** | VPS | VPS | Mail stored off the NAS; webmail reaches it over the internet. |
|
| **C. Stalwart on a VPS** | VPS | VPS | Mail stored off the NAS; webmail reaches it over the internet. |
|
||||||
|
|
||||||
|
**Chosen (2026-10-10): option A** — everything on the QNAP; see `docs/mail-server-network.md` for the network, DNS and port plan and the connection checks.
|
||||||
|
|
||||||
### D.2 Infrastructure
|
### D.2 Infrastructure
|
||||||
- `stalwart` service in both compose stacks (dev `webmail`, prod `webmail-prod` — never share the project name), image pinned to an exact version.
|
- `stalwart` service in both compose stacks (dev `webmail`, prod `webmail-prod` — never share the project name), image pinned to an exact version.
|
||||||
- **Stores:** data store = a separate `stalwart` database on the existing Postgres; blob store = filesystem under `DATA_ROOT/stalwart` (bind mount, not a named volume). `backup.sh` and `webmail.sh update` (backup → migrate → roll → health-gate) then cover it; no RocksDB to snapshot separately.
|
- **Stores:** data store = a separate `stalwart` database on the existing Postgres; blob store = filesystem under `DATA_ROOT/stalwart` (bind mount, not a named volume). `backup.sh` and `webmail.sh update` (backup → migrate → roll → health-gate) then cover it; no RocksDB to snapshot separately.
|
||||||
|
|||||||
Reference in New Issue
Block a user