Published7 min read

Zero-Inbound-Port Homelab Mail: The Planned SES, S3 Store-and-Forward & Stalwart Setup

How to self-host private email without port forwarding, dynamic IP blacklists, or reboot bounces—combining Amazon SES, an encrypted S3 relay bucket, Stalwart, and Roundcube.

Note

Blueprint Status (Planned Target Architecture): This article documents the planned email architecture conceptualized for HOME-LAB.net. Only the public static showcase is live today—the internal split-horizon DNS/TLS layers, mail engine, and local LAN core are queued to be set up once the UniFi core network and lab server hardware upgrades are complete.

Hosting an email server on a residential internet connection has historically been considered an operational death wish.

Between residential ISPs unconditionally blocking inbound TCP Port 25, dynamic residential IP blocks being permanently flagged on global Spamhaus/CBL blacklists, and homelab reboots bouncing inbound messages back to senders with cryptic 550 Connection Refused errors, running a traditional Postfix/Dovecot stack at home is notoriously fragile.

For HOME-LAB.net, I conceptualized a decoupled split-horizon mail architecture: Serverless Inbound Store-and-Forward via Amazon SES & S3, paired with an Outbound HTTPS Pull into Stalwart, Roundcube Webmail, and a Straight Outbound Relay through Amazon SES.

Here is how the planned blueprint works.


1. The Core Architecture

Local Homelab Core (Zero Open Ports)

AWS Tokyo (ap-northeast-1)

1. Port 25 Inbound SMTP

2. Write raw .eml

3. Outbound HTTPS 443 Pull

4. Local Mail Delivery

A. Submit Outbound Email

B. Sign 2048-bit DKIM & TLS Relay

C. Deliver to Destination

Route 53 MX & Amazon SES Inbound(SPF / DKIM / Anti-Virus Scan)

Encrypted S3 Relay Bucket(7-day lifecycle retention)

Amazon SES Outbound SMTP Relay(Port 587 STARTTLS • Tier-1 IPs)

Stalwart Mail Server(Single Rust Binary • RocksDB on Host ZFS)

Roundcube Webmail & Mail Clients(Local IMAP / JMAP • Port 587)

External Sender(Gmail, M365, etc.)

External Recipient(Gmail, M365, etc.)


2. Inbound: Serverless SES → S3 Store-and-Forward

Instead of trying to route raw inbound SMTP directly through a residential firewall, the inbound flow leverages AWS as a resilient, zero-maintenance buffer:

Step 1: Edge MX Termination

The public Route 53 MX record will point directly to Amazon SES in Tokyo:

home-lab.net.  IN  MX  10 inbound-smtp.ap-northeast-1.amazonaws.com.

When an external sender transmits a message:

  • Amazon SES terminates the connection on AWS edge infrastructure over standard port 25 with opportunistic TLS.
  • SES automatically evaluates incoming SPF records, checks cryptographic DKIM signatures, validates DMARC alignment, and runs anti-virus and anti-spam heuristics.

Step 2: The S3 Store-and-Forward Relay

An SES Receipt Rule will capture messages destined for *@home-lab.net:

  1. Raw MIME Storage: SES writes the raw, byte-for-byte RFC 5322 .eml payload directly into an encrypted S3 bucket (s3://home-lab-net-mail-relay/inbound/).
  2. Encryption at Rest: Objects are encrypted using server-side AES-256 (aws:kms or AES256).
  3. Automated Lifecycle Policy: A 7-day expiration rule ensures obsolete files are purged automatically if unretrieved, keeping storage minimal.

Step 3: Zero-Inbound-Port Pull

This is the architectural linchpin that eliminates port forwarding:

  • A local worker process (or Stalwart’s native S3 ingest integration) inside the homelab will poll the S3 bucket using restricted IAM credentials (s3:GetObject, s3:DeleteObject).
  • Because the connection is initiated outbound from the homelab to AWS over HTTPS (TCP 443), zero inbound ports are opened on the residential router.
  • Newly retrieved .eml files will be ingested into Stalwart Mail Server, which indexes message headers, full-text bodies, and attachments into its local RocksDB database on ZFS.
  • Once successfully committed to local disk, the worker deletes the object from S3.
Tip

Power Outage & Reboot Immunity: If the homelab server is offline for maintenance, reboots during a kernel upgrade, or loses residential fiber connectivity, zero emails are lost. Senders never receive a connection bounce. Messages safely queue in S3 and are ingested the moment the server boots back up.


3. Webmail & Identity: Roundcube + Authelia

Once ingested into Stalwart, messages will be presented through a clean local webmail interface:

  • Stalwart Mail Server: A modern, single-binary mail engine written in Rust. It replaces the legacy multi-daemon combination of Postfix, Dovecot, OpenDKIM, and SpamAssassin, delivering blazingly fast JMAP and IMAP performance.
  • Roundcube Webmail: Planned at https://mail.home-lab.net behind the local Caddy reverse proxy with DNS-01 wildcard TLS certificates.
  • Authelia SSO (XOAUTH2 / OIDC): Will provide unified single sign-on across the entire homelab so a single WebAuthn hardware passkey or biometric login unlocks webmail, Immich, GitLab, and internal dashboards.
  • Mobile Clients: Native mail applications on iOS and macOS will connect directly to Stalwart over IMAP/JMAP whenever connected to home Wi-Fi or roaming over the AlwaysRoute (alwaysroute.com) WireGuard on-demand tunnel.

4. Outbound: “Straight Outbound” Relay via Amazon SES

Residential IP ranges are hardcoded into global spam blocklists (Spamhaus, SpamCop, Barracuda). Attempting to deliver outbound mail directly from a home connection results in near-instant spam folder placement or outright rejection.

My planned setup resolves this through a straight outbound relay:

  1. Client Submission: The user sends an email from Roundcube or a mobile client. The client authenticates against Stalwart over local SMTP submission (Port 587 with STARTTLS).
  2. Local DKIM Signing: Stalwart cryptographically signs the outbound message using home-lab.net’s 2048-bit private DKIM key (d=home-lab.net, s=mail).
  3. Straight Outbound Relay: Stalwart relays the signed message directly to Amazon SES:
    Endpoint: email-smtp.ap-northeast-1.amazonaws.com
    Port:     587 (STARTTLS)
    Auth:     Dedicated IAM SMTP Credentials
  4. Global Edge Delivery: Amazon SES accepts the pre-authenticated message and transmits it to destination servers (Google Workspace, Microsoft 365, ProtonMail) from Amazon’s warmed, high-reputation IP pool.

Cryptographic Alignment in Route 53

Deliverability is enforced via strict, declarative DNS records:

  • SPF: v=spf1 include:amazonses.com ~all
  • DKIM: 3× Route 53 CNAME records provisioned via Amazon SES Easy DKIM (*._domainkey.home-lab.net).
  • DMARC: Strict enforcement policy rejecting unaligned spoofed mail without noisy aggregate report spam:
    _dmarc.home-lab.net.  IN  TXT  "v=DMARC1; p=reject; pct=100"

5. Architectural Comparison

DimensionTraditional Self-Hosted MailHOME-LAB.net Planned Architecture
Inbound Port 25Required on home router (blocked by most ISPs)Blocked & Closed (Outbound HTTPS pull via S3)
Outbound Port 25Blocked by ISP / Blacklisted on SpamhausNot used (Straight Port 587 TLS relay via Amazon SES)
Reboot ResilienceOffline server causes 550 Connection RefusedZero-bounce (S3 acts as an elastic, durable buffer)
DeliverabilityPoor (residential IP reputation issues)100% Inbox Placement (Valid SPF, DKIM, DMARC on SES IPs)

6. Build To-Do Checklist

Here is the concrete implementation roadmap I’ll be working through to bring this stack online on the Proxmox VE host:

  • Phase 1 — AWS SES & S3 Relay (Terraform): Provision the ap-northeast-1 SES domain identity, Easy DKIM CNAME records, encrypted home-lab-net-mail-relay S3 bucket (7-day lifecycle), and SES Inbound Receipt Rule.
  • Phase 2 — Outbound SES Production Access: Request SES sandbox exit in Tokyo and generate least-privilege IAM credentials for both the S3 inbound puller (s3:GetObject, s3:DeleteObject) and Port 587 SMTP outbound relay.
  • Phase 3 — Stalwart LXC on Host ZFS: Provision a dedicated unprivileged Debian LXC container on Proxmox VE with a bind-mounted NVMe ZFS dataset (rpool/data/stalwart) and configure RocksDB storage + S3 inbound polling.
  • Phase 4 — Roundcube + Authelia OIDC (XOAUTH2): Deploy Roundcube behind Caddy (https://mail.home-lab.net) and wire OIDC token authentication so Authelia passkey sessions log straight into webmail without a second password prompt.
  • Phase 5 — Fault-Injection & Reboot Testing: Shut down the Stalwart LXC container, send external test emails from Gmail/ProtonMail, verify they queue cleanly in S3 with zero bounces, and confirm automatic ingestion upon container boot.

7. What’s Next

This architecture bridges the best of both worlds: complete local storage on the Proxmox host’s native ZFS on the inside, with enterprise-grade reliability and zero open firewall ports on the outside.

This project is queued up right after I finish upgrading the UniFi core network and the lab server itself. Once the hardware and core network foundation are in place, I’ll work through the checklist above and share the Terraform modules, IAM least-privilege policies, and Stalwart configuration notes in upcoming logs.

Ed Stuurman

About the author

Ed Stuurman

Infrastructure and reliability engineer based in Japan. Passionate about resilient systems, bare-metal hardware, cloud automation with Terraform, and all things homelab.

Contact

Thoughts or questions on this article?

Found a bug, tested a similar setup, or want to discuss the details? Drop a message below.

Emails are delivered directly to ed@stuurman.com.