Try Stalwart, a Modern Rust Mail Server
Install Stalwart, a single-binary Rust mail server, with SMTP, IMAP4, JMAP, DKIM, SPF, and DMARC configured end-to-end on a Linux VPS.
Before you start
- ▸A VPS or dedicated server with a public static IP and root or sudo access
- ▸A domain name you control with the ability to edit DNS records (A, MX, PTR, TXT)
- ▸Ports 25, 465, 587, 993, and 8080 not already in use by another mail daemon
- ▸PTR (reverse DNS) record configured through your VPS provider's control panel
Stalwart is a full-featured mail server written in Rust that speaks JMAP, IMAP4, and SMTP under one binary. It ships DKIM signing, SPF checking, DMARC enforcement, and built-in spam filtering without bolting on a dozen separate daemons. If you are tired of wrangling Postfix + Dovecot + OpenDKIM + Rspamd, Stalwart is worth a serious look. This guide walks you through a production-ready installation on a fresh VPS with a real domain.
Prerequisites and DNS Prep
Before touching the server, get DNS right. Stalwart cannot compensate for missing records, and mail will bounce or be flagged as spam until DNS is correct.
- A dedicated hostname for the mail server, e.g. mail.example.com, with an A (and AAAA) record pointing to your server's IP.
- An MX record for example.com pointing to mail.example.com with priority 10.
- A PTR (reverse DNS) record for your server IP resolving to mail.example.com — set this through your VPS provider's control panel.
- Ports 25, 465, 587, 993, and 8080 (admin UI) open in your firewall.
Install Stalwart
Option A — Official install script (any systemd distro)
Stalwart provides a self-contained installer that detects your architecture and drops a single binary plus a systemd unit.
curl -fsSL https://get.stalw.art/install.sh | sudo bash -s -- --help
Review the script first, then run the real install targeting the mail package (includes SMTP, IMAP, JMAP):
curl -fsSL https://get.stalw.art/install.sh | sudo bash -s -- --component mail
The installer creates /opt/stalwart-mail/, writes /etc/systemd/system/stalwart-mail.service, and prints an auto-generated admin password. Copy that password immediately.
Option B — Manual binary install
Download the latest release tarball from GitHub releases, pick the binary matching your CPU (x86_64-unknown-linux-gnu for most VPS):
RELEASE=$(curl -s https://api.github.com/repos/stalwartlabs/mail-server/releases/latest \
| grep tag_name | cut -d '"' -f4)
curl -LO "https://github.com/stalwartlabs/mail-server/releases/download/${RELEASE}/stalwart-mail-x86_64-unknown-linux-gnu.tar.gz"
tar xzf stalwart-mail-*.tar.gz
sudo mv stalwart-mail /usr/local/bin/
sudo stalwart-mail --install
Open Firewall Ports
Ubuntu / Debian (ufw)
sudo ufw allow 25/tcp
sudo ufw allow 465/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp
sudo ufw allow 8080/tcp
sudo ufw reload
Fedora / RHEL / Rocky (firewalld)
sudo firewall-cmd --permanent --add-service=smtp
sudo firewall-cmd --permanent --add-service=smtps
sudo firewall-cmd --permanent --add-service=smtp-submission
sudo firewall-cmd --permanent --add-service=imaps
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Arch (nftables)
sudo nft add rule inet filter input tcp dport { 25, 465, 587, 993, 8080 } accept
sudo nft list ruleset | sudo tee /etc/nftables.conf
Initial Configuration via Web UI
Stalwart's management interface runs on port 8080. Point a browser at http://mail.example.com:8080 and log in with username admin and the password the installer printed.
- Navigate to Settings → Server → Hostname and set it to
mail.example.com. - Under Settings → Server → TLS, select ACME (Let's Encrypt) and enter your domain. Stalwart handles certificate renewal automatically via the ACME HTTP-01 challenge on port 80, or TLS-ALPN-01 on 443. Make sure port 80 or 443 is reachable.
- Set your primary domain under Directory → Domains → Add Domain:
example.com.
DKIM, SPF, and DMARC
DKIM
After adding your domain, Stalwart auto-generates a 2048-bit RSA DKIM key pair. Go to Directory → Domains → example.com → DKIM and copy the TXT record value shown. Add it to your DNS as:
# DNS TXT record (add via your DNS provider's control panel):
# Name: stalwart._domainkey.example.com
# Type: TXT
# Value: v=DKIM1; k=rsa; p=MIIBIjANBgkq... (copied from UI)
SPF
Add a TXT record on the bare domain:
# Name: example.com
# Type: TXT
# Value: v=spf1 mx a:mail.example.com ~all
DMARC
# Name: _dmarc.example.com
# Type: TXT
# Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; adkim=s; aspf=s
Start with p=quarantine while you confirm delivery is working, then move to p=reject once you are confident. Stalwart will process incoming DMARC reports if you route that address to a local mailbox.
Create Accounts and Aliases
In the web UI go to Directory → Accounts → Add Account. Fill in the username, email address, and initial password. For aliases (e.g. postmaster@example.com → admin), use Directory → Aliases.
You can also manage accounts from the CLI using the HTTP management API:
curl -u admin:PASSWORD -X POST http://localhost:8080/api/principal \
-H 'Content-Type: application/json' \
-d '{"type":"individual","name":"alice","emails":["alice@example.com"],"secrets":["ChangeMe123!"]}'
Enable and Start the Service
sudo systemctl daemon-reload
sudo systemctl enable --now stalwart-mail
sudo systemctl status stalwart-mail
Expected output shows active (running). The log appears in the journal:
sudo journalctl -u stalwart-mail -f
Configure JMAP Access
JMAP (RFC 8620 / RFC 8621) is Stalwart's primary protocol and offers faster, more efficient mail access than IMAP. It is enabled by default on the same HTTPS port (443 when TLS is configured). The JMAP session URL is:
https://mail.example.com/jmap/
Clients like Meli or any JMAP-capable app point at this URL. IMAP4 on port 993 (IMAPS) remains fully available for traditional clients like Thunderbird or Apple Mail — no extra config needed.
Verify End-to-End Delivery
Test outbound with swaks
sudo apt install swaks # or: sudo dnf install swaks / sudo pacman -S swaks
swaks --to test@example.net \
--from alice@example.com \
--server mail.example.com \
--port 587 \
--auth LOGIN \
--auth-user alice@example.com \
--auth-password 'ChangeMe123!' \
--tls
Check DKIM and SPF with an external tool
# Send a test message to mail-tester.com's disposable address and check the score.
# Or use: https://www.learndmarc.com/ for a quick DMARC report.
Check MX and DNS records
dig MX example.com +short
dig TXT stalwart._domainkey.example.com +short
dig TXT _dmarc.example.com +short
Troubleshooting
- TLS cert not issued: Confirm port 80 or 443 is open and your A record is live. Check
journalctl -u stalwart-mail | grep -i acme. - Port 25 blocked: Many VPS providers block outbound port 25 by default. Open a support ticket to unblock it; this is unrelated to Stalwart.
- DKIM verification failing: DNS propagation can take up to 48 hours. Use
dig TXT stalwart._domainkey.example.comto confirm the record is visible before blaming Stalwart. - Mail going to spam: Verify your PTR record matches your hostname exactly. A mismatched or missing PTR is the most common reason legitimate mail is flagged.
- Cannot log into IMAP: Ensure TLS is fully provisioned; most clients refuse plain-auth. Check
openssl s_client -connect mail.example.com:993for certificate errors. - Service not starting after reboot: Run
sudo systemctl cat stalwart-mailto verify the unit file path andsudo systemd-analyze verify stalwart-mail.servicefor unit syntax errors.
Frequently asked questions
- Does Stalwart replace Postfix and Dovecot entirely?
- Yes. Stalwart is a single binary that handles SMTP (inbound and outbound), IMAP4, and JMAP. You do not need Postfix, Dovecot, OpenDKIM, or a separate spam filter for a basic production setup.
- What mail clients work with Stalwart's JMAP endpoint?
- Any JMAP-capable client works, including Meli and future versions of Thunderbird (JMAP support is in active development there). All traditional IMAP clients like Thunderbird, Apple Mail, and K-9 Mail also work normally on port 993.
- Can I migrate existing mailboxes from Dovecot into Stalwart?
- Stalwart supports importing mailboxes in Maildir and mbox formats via its CLI import tool (stalwart-mail import). Run it while the service is stopped, or use the online import API for live migration.
- Is Stalwart suitable for multi-domain hosting?
- Yes. You can add multiple domains under Directory → Domains, each with its own DKIM keypair. SPF and DMARC records must be configured in DNS for each domain separately.
- How does Stalwart handle spam filtering without Rspamd?
- Stalwart ships a built-in spam and phishing filter that uses statistical analysis, DNS blocklists, and reputation checks. It is configurable through the web UI under Settings → Spam Filter and is sufficient for most deployments.
Related guides
Configure Prometheus Alertmanager
Configure Prometheus Alertmanager with routing trees, receivers, inhibition rules, grouping, Go templates, and PagerDuty/Slack on-call integrations.
Build an Intranet Server on Linux
Set up a complete small-office intranet on one Linux box: Nginx web server, dnsmasq local DNS, Samba file sharing, and a Wiki.js team wiki.
Build an nftables Firewall Script
Build a complete nftables firewall from scratch: tables, chains, sets, default-deny input policy, service allowlisting, and persistent systemd configuration.
Caddy as a Reverse Proxy
Set up Caddy as a reverse proxy with automatic HTTPS, load balancing, WebSocket passthrough, reusable snippets, and header control — no certbot required.