Documentation Index
Fetch the complete documentation index at: https://docs.augustin.ai/llms.txt
Use this file to discover all available pages before exploring further.
Stalwart Mail Server
Self-hosted mail server with a privacy-focused architecture that keeps the home IP hidden.
Overview
Stalwart is a modern, open-source mail server written in Rust that supports JMAP, IMAP, POP3, SMTP, CalDAV, CardDAV, and WebDAV.
- Hostname:
stalwart.augustin.ai
- Primary Domain:
augustin.ai
- Primary Email:
root@augustin.ai
- Catch-all:
*@augustin.ai → routes to primary account
:::note
Stalwart does not include a built-in webmail client. The web interface at stalwart.augustin.ai is for administration only. To read emails, use an IMAP client (Apple Mail, Thunderbird, etc.) or deploy a separate webmail container. Stalwart plans to add webmail in 2026.
:::
Architecture
Inbound: Internet → Cloudflare MX → Email Routing → Worker → JMAP API → Stalwart
Outbound: Stalwart → Resend SMTP relay → Internet
Access: IMAP via Tailscale (iPhone) / Cloudflare Tunnel TCP (laptop)
Components
| Component | Purpose | Status |
|---|
| Stalwart | Mail server | ✅ Running |
| Cloudflare Email Routing | Receive inbound mail | ✅ Configured |
| Cloudflare Worker | Forward mail to Stalwart via JMAP | ✅ Deployed |
| Cloudflare Tunnel (HTTP) | Admin/JMAP access | ✅ Working |
| Cloudflare Tunnel (TCP) | IMAP for work laptop | 🔲 To configure |
| Tailscale | IMAP for iPhone | 🔲 To set up |
| Resend | Outbound SMTP relay | ✅ Configured |
Storage
| Store | Purpose | Backend |
|---|
| Data Store | Metadata, folders, settings | RocksDB |
| Blob Store | Emails, attachments | RocksDB |
| Full-text Search | Email search indexing | RocksDB |
| Lookup Store | Caching, sessions | RocksDB |
Ports
| Port | Protocol | Purpose | Access Method |
|---|
| 25 | SMTP | Receiving external mail | Not used (using Worker) |
| 465 | SMTPS | Client mail submission | Tailscale / CF Tunnel TCP |
| 587 | SMTP+STARTTLS | Client mail submission | Tailscale / CF Tunnel TCP |
| 993 | IMAPS | Client mail retrieval | Tailscale / CF Tunnel TCP |
| 443 | HTTPS | Admin, JMAP API | Traefik / CF Tunnel HTTP |
| 8080 | HTTP | Internal (Traefik backend) | Not exposed |
| 4190 | ManageSieve | Mail filter rules | Optional |
Setup Progress
Phase 1: Core Deployment ✅
Phase 2: Storage Configuration ✅
Phase 3: Outbound Mail (Resend) ✅
Phase 4: Client Access
Phase 5: Inbound Mail (Cloudflare Worker) ✅
Phase 6: Domain & DNS ✅
DNS Records
| Type | Name | Content |
|---|
| MX | augustin.ai | route1.mx.cloudflare.net (priority 50) |
| MX | augustin.ai | route2.mx.cloudflare.net (priority 64) |
| MX | augustin.ai | route3.mx.cloudflare.net (priority 82) |
| TXT | augustin.ai | v=spf1 include:_spf.mx.cloudflare.net ~all |
| TXT | _dmarc.augustin.ai | v=DMARC1; p=reject; rua=mailto:postmaster@augustin.ai; ruf=mailto:postmaster@augustin.ai |
| TXT | 202602r._domainkey.augustin.ai | RSA DKIM key |
| TXT | 202602e._domainkey.augustin.ai | Ed25519 DKIM key |
| TXT | _smtp._tls.augustin.ai | v=TLSRPTv1; rua=mailto:postmaster@augustin.ai |
| TXT | resend._domainkey.augustin.ai | Resend DKIM key |
| Type | Name | Content | Purpose |
|---|
| CNAME | autoconfig.augustin.ai | stalwart.augustin.ai | Email client auto-config |
| CNAME | autodiscover.augustin.ai | stalwart.augustin.ai | Email client auto-discovery |
| SRV | _imaps._tcp.augustin.ai | 0 1 993 stalwart.augustin.ai | IMAP service discovery |
| SRV | _submissions._tcp.augustin.ai | 0 1 465 stalwart.augustin.ai | SMTP service discovery |
| SRV | _jmap._tcp.augustin.ai | 0 1 443 stalwart.augustin.ai | JMAP service discovery |
Cloudflare Worker
The Worker (cloudflare-worker.js) handles inbound email:
- Receives raw email from Cloudflare Email Routing
- Looks up recipient in Stalwart accounts (supports catch-all)
- Gets JMAP session to find account ID
- Uploads email blob via JMAP
- Imports email to recipient’s Inbox
Client Configuration
JMAP Clients
| Setting | Value |
|---|
| JMAP URL | https://stalwart.augustin.ai/.well-known/jmap |
| Username | root@augustin.ai |
IMAP/SMTP Clients
| Setting | Value |
|---|
| IMAP Server | stalwart.augustin.ai:993 (SSL/TLS) |
| SMTP Server | stalwart.augustin.ai:465 (SSL/TLS) |
| Username | root@augustin.ai |
:::note
IMAP/SMTP require direct access via Tailscale or Cloudflare Tunnel TCP (not yet configured).
:::
Backup & Recovery
Backup Strategy
All email data is local in RocksDB (blobs, metadata, mailbox structure, FTS index, settings).
A nightly JMAP export runs at 2:45am via stalwart/backup-email.sh, using stalwart-cli export account to dump the full account (emails, mailboxes, identities, Sieve scripts, vacation responses) into stalwart/data/export/. The 3:00am restic backup then sends this to AWS S3.
| Backup Layer | What | Where | Schedule |
|---|
| JMAP export | Full account (emails + config) | stalwart/data/export/ | Daily 2:45am |
| Restic → S3 | All of ~/apps including export | AWS S3 (augustin-backups/i3) | Daily 3:00am |
Recovery Scenarios
- Container dies (data intact) —
docker compose up -d, Stalwart reconnects to RocksDB automatically
- Full restore from restic — restore
stalwart/ from restic, start container
- Clean slate rebuild — restore from restic, deploy fresh container, reimport via
stalwart-cli import account
- Stalwart is down, need to read email — inbound mail queues at Cloudflare (~24h retry), latest JMAP export on disk contains raw
.eml files
See stalwart/README.md for detailed recovery commands.
Future Enhancements