Self-host
Postern is built to run as a small set of co-located services behind a reverse proxy. This page is the architectural map of a self-hosted deployment — what the pieces are, where they sit, and what’s in V1 scope.
Components
Section titled “Components”| Component | What it is | Stack |
|---|---|---|
| Agent + admin API | The /v1 REST surface; token/agent/mailbox orchestration | Go (cmd/postern-api) |
| Authoritative DNS | Serves per-tenant A/MX/SPF/DKIM/DMARC for delegated subdomains | Go + miekg/dns (cmd/postern-dns), DB-backed |
| MCP server | The agent tool surface incl. wait_for_email | TypeScript (postern/mcp), stdio + HTTP |
| Console | Human management UI (agents, keys, domains, inboxes) | Next.js |
| Send backend | Authenticated sending | Azure Communication Services |
| Receive backend | Full IMAP mailbox store | WildDuck |
The Go API reuses the existing provisioning core (internal/provisioning, internal/mailserver,
internal/store, internal/auth), which is why it lives in the shared Go module.
Deployment shape
Section titled “Deployment shape”V1 deploys to nested mszazu.com subdomains, co-located on one host behind the reverse proxy:
| Host | Serves |
|---|---|
agents.mszazu.com | Marketing website |
app.agents.mszazu.com | Console |
api.agents.mszazu.com | API + MCP |
ns1.mszazu.com / ns2.mszazu.com | Authoritative DNS (UDP/TCP 53) |
docs.agents.mszazu.com | This documentation |
Mailboxes live on *.mszazu.com nested labels. Images are prebuilt and deployed with the Uncloud
--no-build flow. co-located in V1, isolate later
Configuration
Section titled “Configuration”The whole client and server stack is driven by POSTERN_API_BASE_URL (and a key). Point everything at
your own host and it works the same way:
export POSTERN_API_BASE_URL="https://api.postern.internal"export POSTERN_API_KEY="pk_agent_…"| Variable | Used by | Purpose |
|---|---|---|
POSTERN_API_BASE_URL | SDK, MCP, your clients | Base URL of the API (mock for offline). |
POSTERN_API_KEY | SDK, MCP | Scoped agent or enrollment key. |
POSTERN_MOCK | MCP | 1 to force offline fixtures. |
SITE_URL | docs/website build | Public host for canonical URLs. |
Security model to preserve
Section titled “Security model to preserve”If you self-host, carry the same discipline the hosted service enforces:
- Every API call is tenant-scoped by
customer_idderived from the key, never from client input. - Agent keys are scoped, revocable, and audited; no org-wide key reaches an MCP host.
- Inbound webhooks are HMAC-signed and timestamped.
- Credential/download links are signed, short-TTL, and (soon) single-use.
See Enrollment tokens & scopes and Errors for how these show up at the API.
V1 scope & what’s deferred
Section titled “V1 scope & what’s deferred”| In V1 | Deferred |
|---|---|
One-call inbox on mszazu.com subdomains (mandatory ACS sender) | Real-money / mainnet x402, production billing |
| Send + receive + threaded reply | Self-serve domain purchase (ops-assisted first) |
| Scoped enrollment + agent keys (issue/scope/expire/revoke/audit) | spring* isolation as a self-serve toggle, BYO-domain |
Hosted MCP with wait_for_email | Semantic search / auto-labeling |
| HMAC-signed inbound webhooks | Dedicated IPs + warmup engine + cold-outreach tooling |
| Console + x402 test mode | SOC2 / SAML / EU residency |
| Go SDK + REST/OpenAPI, NS-delegation DNS | Biscuit offline attenuation, AP2 mandates |
- Domains & onboarding — the DNS server in context.
- API reference — the surface you’d run.
- Rate limits & quotas — limits to configure.