[1.2.0] The second MINOR after 1.0.0: domain administrators with per-domain scope, a panel visual refresh on the SelfPost palette, and refinements to navigation and the send log. Upgrading runs one SQLite migration (`0005_panel_users`); the single administrator becomes a global user. Added: - panel: **domain-admin role** — global administrators manage panel users and Fixed: - Docker build: `LICENSE` is no longer excluded by `.dockerignore`, so the - panel: on signed-in pages with a narrow card (**Settings**, the user form) Changed: - panel: navigation session icons are distinct — **Settings** uses a gear, - panel: `/` redirects domain administrators to `/domains`; global users still - panel: **Sign out** in the navigation column uses the same type size and - panel: **visual style** brought in line with the SelfPost mark — brick accent - panel: the send log's **status is a badge**, in the same ok/warn/error/unknown … (1 more in CHANGELOG) [1.2.1] Panel refinements after 1.2.0: navigation icons, status-badge centreing, drill-down back-link placement, and safeguards for the sole global administrator. Upgrading is a tag bump; no migration. Fixed: - panel: status badge text sat low in the box (and below the heading or label - panel: the **Users** navigation icon was two full silhouettes with staggered - panel: the **Settings** navigation icon was a sun-with-rays (circle plus - panel: the user create/edit form placed «Back to users» at the bottom of the Changed: - panel: the user edit form disables role change and delete for the only global - panel: the user create/edit form hides **Assigned domains** when the role is - panel: **Settings** shows panel credentials and DMARC aggregate reports side [1.2.2] Status page layout after 1.2.1: paired cards in a wide column, denser machine and check copy, and a user-form checkbox fix. Upgrading is a tag bump; no migration. Changed: - panel: **Status** is wide again so paired cards fill the column. Layout: Fixed: - panel: cards inside `.split` used `margin: 0 auto`, which in a CSS grid - panel: on the user create/edit form, **Assigned domains** checkboxes stacked [1.2.3] Domain detail layout and panel polish after 1.2.2. Upgrading is a tag bump; no migration. Changed: - panel: the domain detail page is wide with paired cards (DKIM+SPF ‖ DMARC; - panel: Domains list — **Add domain** sits beside the domain field; the - panel: page URLs, browser titles, and headings are aligned — **Settings** is Fixed: - image: `mail.log` rotation no longer silently stops when the build context [1.2.4] Level-2 rate-limit semantics inverted after 1.2.3, plus a small DNS field height fix. Upgrading is a tag bump; no migration. Changed: - rate limiting (level 2): domain ceilings apply to every client IP (no IP Fixed: - panel: on the domain DNS status grid, the Type (TXT) field height matches [1.2.5] Rate-limit form polish after 1.2.4. Upgrading is a tag bump; no migration. Changed: - panel: rate-limit forms refined — level-1 backstop as muted copy on the Squashed CHANGELOG sections: [1.2.0], [1.2.1], [1.2.2], [1.2.3], [1.2.4], [1.2.5]. Full detail: CHANGELOG.md (1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5).
110 lines
4.1 KiB
Markdown
110 lines
4.1 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 **outbound SMTP relay** with a web control panel,
|
|
shipped as a single Docker image. It sends mail directly to the internet from
|
|
your own IP with per-domain DKIM signing.
|
|
|
|
**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.
|
|
|
|
---
|
|
|
|
## 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, OpenDKIM, and the panel 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 global + domain-admin roles; managing
|
|
**multiple sending domains** under one global administrator is in scope (see
|
|
below)
|
|
- Inbound antispam/antivirus (rspamd, ClamAV, etc.)
|
|
- A custom MTA — Postfix is used as-is
|
|
- Dovecot or a full mail stack for SASL — Cyrus SASL (`sasldb2`) only
|
|
|
|
The **domain-admin** role ships in the current line (global administrator plus
|
|
domain administrators with assigned domains). The optional **inbound relay** is
|
|
the main agreed **1.x+** extension still on the
|
|
[roadmap](roadmap.md) — it targets a 1.x MINOR bump by default; a 2.x major
|
|
remains possible pending implementation. Items marked *candidate* in the
|
|
roadmap 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.
|