Files
selfpost/docs/product.md
T
mix 60e08e802e release: 1.2.0: Panel 1.2.0-1.2.5: layout, RBAC, tests, GUI and CI fixes
[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).
2026-09-22 15:24:52 +03:00

4.1 KiB

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; install and operations in guide.md; as-built technical detail in 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.

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 — 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.