Files
selfpost/docs/product.md
T
mixandClaude Opus 5.5 2cfd239d16
test / test (push) Canceled after 0s
docs: panel-dkim-signing stage 3 - the documents without OpenDKIM
architecture § OpenDKIM becomes § DKIM signing (keys, the selector table
and when it is rewritten, the two sockets, what is signed and the limits,
the old tree); the process table, start order, liveness, the mail-path
diagram, § Sender check, Persistence and the restore Resync follow the
code. security.md: the panel signs with the login's key, the keys are the
panel's alone, group selfpost and CAP_KILL as they are now; OpenDKIM's
accepted risks go; new ones: what sendmail(1) submits is signed as the
server, Sender: is signed but not judged (the owner's decision), and
go-milter keeps every header per session, so the signer's 1 MiB refusal
does not bound the library's copy. guide: Health, the container log's
dkim-signer lines, backups, the long-line limit, and upgrading to 2.8.0 -
with the rollback to 2.7.x: its start reads the queue as its own postfix
(uid 101) before it hands the queue over, so the hand-over by name is run
in the 2.7.x image first (measured on a copy of the test server's queue:
postsuper failed before, passed after). development, README, SECURITY,
product, the assumptions register's header: what left the image.
entrypoint.sh: a comment, the rollback note as the guide gives it. Plan
stage 3 lines ticked, roadmap 12/14.

Written by four agents, one document each, against a brief of what the
code does; reviewed here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:56:56 +03:00

126 lines
5.0 KiB
Markdown

# SelfPost — product boundaries
**What this file is.** Stable product definition for SelfPost v1.0: purpose,
deployment assumptions, explicit out-of-scope items, and the multi-domain
model. User-facing overview in [README.md](../README.md); install and operations
in [guide.md](guide.md); as-built technical detail in
[architecture.md](architecture.md).
---
## Purpose
SelfPost is a self-hosted **SMTP relay** with a web control panel, shipped as a
single Docker image. It sends mail directly from your server with per-domain
DKIM signing; an optional inbound relay forwards mail on port 25 without
storing it.
**Primary workflow:** configure the relay once (domains, DKIM, SASL
applications), then point scripts and apps at the SMTP endpoint. SelfPost
delivers as the configured sending domain.
## Positioning
| | Text |
|---|---|
| Stamp subtitle | SELF-HOSTED SMTP RELAY |
| Wordmark | The stamp's own letter outlines without the stamp (`docs/assets/selfpost-wordmark.svg`, `-ink` for light grounds) — for places too small for the stamp, such as the panel header |
| Tagline | YOUR SMTP. YOUR RULES. |
| Hero line (README, GitHub) | Self-hosted SMTP relay with a web panel — one Docker image, no provider. |
Brand assets and metrics: [docs/assets/selfpost-proof.html](assets/selfpost-proof.html).
---
## Deployment context (fixed assumptions)
These constraints are intentional; changing them requires an explicit product
decision:
1. **VPS or home server** — one image for both. Raspberry Pi and similar boards
are not a current target but not ruled out forever.
2. **Send from your own IP (DIY)** — no intermediate relay provider. Requires
outbound port 25, static IP, and configurable PTR/rDNS from the operator.
3. **Single container** — Postfix and the panel, which signs outgoing mail
with DKIM itself, run under one `supervisord` inside one image.
4. **Panel is internet-facing** — mandatory security requirements in
[security.md](security.md).
**Infrastructure the operator provides (not SelfPost features):** unblocked
outbound TCP 25, static IP, PTR/rDNS, acceptable IP reputation. SelfPost does
not detect, bypass, or compensate for missing prerequisites; mail simply fails
to deliver when they are absent.
---
## Out of scope
Explicitly excluded to prevent scope creep:
- Inbound mail (IMAP/POP3, mailboxes, delivery to user inboxes)
- Webmail
- Organisations / tenancy beyond the `global` and `domain` roles; managing
**multiple sending domains** under one global administrator is in scope (see
below)
- Inbound antispam/antivirus engines (rspamd, ClamAV, etc.) — SelfPost may
expose a milter hook; it does not ship or start a filter
- A custom MTA — Postfix is used as-is
- Dovecot or a full mail stack for SASL — Cyrus SASL (`sasldb2`) only
The **`domain`** role ships in the current line (a `global` user plus
`domain` users with assigned domains, outbound and inbound separately). The
optional **inbound relay** (backup-MX / forwarder on port 25) ships in `[1.4.0]`, off by default behind
`INBOUND_RELAY_ENABLE`; it is relay/forward, not IMAP/webmail. **Send-log
retention in Settings** ships in `[1.5.0]`. **30-day send statistics** and
**auto level-2 rate limits** ship in `[1.6.0]`. **DMARC aggregate report
ingest** ships in `[1.7.0]`, off by default behind `DMARC_REPORTS_ENABLE`.
Items marked *candidate* in the
[roadmap](roadmap.md) require explicit approval before coding.
---
## Multi-domain model
SelfPost is a **multi-domain outbound relay**. Two linked entities:
### Sending domain
Example: `example.com`. Has its own DKIM key and selector.
### Application (account)
A SASL login/password bound to **one** domain. A domain may have several
applications (e.g. newsletter vs alerts), each with its own credentials, but
each may send **only from its own domain**, never from another.
### From-address mode (per application)
Set when creating or editing an application:
1. **Any address in the domain** — `*@example.com` (wildcard in
`smtpd_sender_login_maps`).
2. **Explicit address list** — only listed From addresses within the domain;
anything else is rejected even if it belongs to the same domain.
In both modes the From address must belong to the application's domain.
### What the panel manages per domain
- DKIM key + selector (shared by all applications on that domain)
- One or more applications (SASL credentials + From mode + optional rate limits)
- DNS guidance (DKIM TXT; reminders for SPF/DMARC)
Adding a domain does **not** create an application automatically.
### Lifecycle
- **Add domain** — record, DKIM key, DNS instructions; no application yet.
- **Add application** — SASL pair (password shown once), From mode, map entries,
`postfix reload`.
- **Delete domain** — removes DKIM key and **all** its applications.
- **Delete application** — removes only that app's SASL and map entries.
This is not multi-tenancy; it is one owner (or a small team with global and
domain-scoped roles) operating several sending domains with independent
application credentials.