
Running your own mail server used to mean gluing together Postfix, Dovecot, Rspamd, and half a dozen config files that all speak different syntax. One misconfiguration and your domain ends up on a blacklist before you even send a single email. Stalwart Mail solves this by packing SMTP, IMAP4rev2, JMAP, POP3, and anti-spam filtering into one single binary, written in Rust, with a clean web admin panel to manage everything.
This Linux server tutorial walks you through the complete process to install Stalwart Mail on Ubuntu 24.04 LTS from a fresh server to a production-ready, TLS-secured mail setup with verified SPF, DKIM, and DMARC. Every step explains not just the command, but the reason behind it. If you follow this guide in order, you will have a fully working mail server that passes authentication checks and delivers to Gmail and Outlook without hitting the spam folder.
What Is Stalwart Mail and Why Use It
Stalwart Mail is an open-source, all-in-one mail server project maintained by Stalwart Labs under the AGPL-3.0 license. It handles every layer of email in one process: message transfer (SMTP), message retrieval (IMAP, POP3, JMAP), filtering, and TLS certificate management.
Traditional setups require Postfix for SMTP, Dovecot for IMAP, and a separate spam filter such as Rspamd. Each has its own configuration language, its own failure modes, and its own upgrade cycle. Stalwart replaces all three with a single binary that consumes under 50 MB of RAM at idle.
Being written in Rust means the server has memory-safety guarantees baked into the language itself. Buffer overflows and use-after-free bugs, which have historically caused security incidents in C-based mail servers, simply cannot compile in Rust. That matters a lot for a service that accepts connections from the entire internet 24 hours a day.
| Feature | Stalwart Mail | Postfix + Dovecot + Rspamd |
|---|---|---|
| Binary count | 1 | 3+ |
| JMAP support | Native | Requires plugin |
| Built-in spam filter | Yes | Separate (Rspamd) |
| TLS auto-renewal | Built-in ACME | Certbot or manual |
| RAM usage (idle) | ~50 MB | ~150-300 MB combined |
Prerequisites Before You Start
Before you begin this configure Stalwart Mail on Ubuntu 24.04 LTS tutorial, make sure each item below is ready. Skipping any one of them will cause a failure at a later step.
- Ubuntu 24.04 LTS server with SSH access
- Root or sudo access on that server
- A registered domain name with access to its DNS settings (Cloudflare, Namecheap, etc.)
- A static public IPv4 address with the ability to set a PTR (reverse DNS) record through your VPS provider panel
- Port 25 unblocked by your VPS provider (AWS and GCP block this by default; Hetzner, Contabo, OVH, and Hostwinds allow it)
- Open firewall ports to allow inbound connections on: 25, 443, 465, 587, 993
- Minimum server resources: 2 vCPUs, 2 GB RAM, 50 GB SSD
- Basic command-line familiarity: navigating directories, running
systemctl, editing text files
Step 1: Update Your Ubuntu 24.04 Server
Always start with a full system update. Ubuntu 24.04 ships with packages that may have known CVEs already patched in the upstream repository. Running the Stalwart installer on an unpatched system leaves those vulnerabilities exposed.
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget ufw
What this does: apt update refreshes the local package index. apt upgrade -y installs all available security and maintenance patches without prompting. The -y flag confirms all prompts automatically.
Why install curl? The official Stalwart install script is fetched over HTTPS using curl with TLS 1.2 enforced. An older version of curl without TLS 1.2 support would fail silently without this flag.
Next, set your server hostname to match your intended mail hostname. Stalwart reads the system hostname during installation and uses it in SMTP HELO greetings. A mismatch causes receiving servers to reject or flag your messages.
sudo hostnamectl set-hostname mail.yourdomain.com
Verify the hostname resolves correctly:
hostname -f
Expected output: mail.yourdomain.com
Step 2: Configure DNS Records Before Installation
This step must come before you run the installer. Some records, especially the PTR/reverse DNS record, can take up to 24 hours to propagate. The ACME TLS certificate request in Step 5 requires valid DNS to succeed. If you skip this and run the installer first, the ACME challenge will fail.
Set Your MX and A Records
Log in to your DNS provider and create the following records:
| Record Type | Host | Value | TTL |
|---|---|---|---|
| A | mail |
Your server’s public IP | 300 |
| MX | @ |
10 mail.yourdomain.com |
300 |
Why the MX record? It tells every mail server on the internet where to deliver messages addressed to your domain. Without it, external servers have no target and delivery silently fails.
Set Your PTR (Reverse DNS) Record
Log in to your VPS provider’s control panel (not your domain registrar) and create a PTR record mapping your server IP to mail.yourdomain.com.
Why the PTR record? When Gmail, Outlook, or any other receiving server gets a connection from your IP, it performs a reverse DNS lookup to verify legitimacy. A missing or mismatched PTR record is one of the top reasons freshly installed mail servers get flagged as spam.
Confirm the PTR record is live using:
dig -x YOUR_SERVER_IP
Expected output should include mail.yourdomain.com in the ANSWER section.
Step 3: Install Stalwart Mail on Ubuntu 24.04 LTS
With the server prepared and DNS records live, you are ready to run the installation. The official Stalwart installer handles binary download, service user creation, systemd unit registration, and the initial configuration directory structure automatically.
Download the Installer
curl --proto '=https' --tlsv1.2 -sSf \
https://get.stalw.art/install.sh -o install.sh
Why save it to a file first? Never pipe an install script directly from the internet into sh without inspecting it. Saving it first lets you review what it does before running it. This is a security best practice for any shell script you did not write yourself.
Run the Installer
sudo sh install.sh
What the installer does automatically:
- Downloads the correct binary for your CPU architecture (x86_64 or ARM64)
- Creates a dedicated
stalwartsystem user with no login shell - Places the binary at
/usr/local/bin/stalwart - Writes the config file to
/etc/stalwart/config.json - Sets up data directories at
/var/lib/stalwart/ - Writes a systemd unit file and starts the service immediately
Retrieve Your Bootstrap Admin Credentials
Stalwart starts in bootstrap mode after the first install. A temporary admin password is generated and printed once to the service log. Retrieve it immediately with:
sudo journalctl -u stalwart -n 200 | grep -A8 'bootstrap mode'
You will see output similar to:
════════════════════════════════════════════════════════════
🔑 Stalwart bootstrap mode - temporary administrator account
username: admin
password: XXXXXXXXXXXXXXXX
════════════════════════════════════════════════════════════
Copy this password now. It appears in the log exactly once. If you miss it, you will need to set a recovery credential manually in /etc/stalwart/stalwart.env and restart the service.
Verify the service is running:
sudo systemctl status stalwart
Expected output: Active: active (running)
Step 4: Complete the Web Setup Wizard
Open a browser and navigate to:
http://YOUR_SERVER_IP:8080/admin
Sign in with admin and the bootstrap password from the previous step. Stalwart runs a five-screen setup wizard.
Wizard Step 1: Server Identity
- Server hostname: Enter
mail.yourdomain.com. This value goes into SMTP HELO greetings, outgoing headers, and TLS certificate requests. It must exactly match your DNS A record. - Default email domain: Enter
yourdomain.com. - Automatically obtain TLS certificate: Leave this enabled. Stalwart requests a free Let’s Encrypt certificate using ACME automatically.
- Generate email signing keys: Leave this enabled. Stalwart generates DKIM keys for your domain to cryptographically sign outgoing messages.
Why is the hostname so critical? If this value does not match your public DNS A record, the ACME TLS challenge fails, receiving servers see a mismatched HELO, and your messages fail DMARC alignment checks.
Wizard Step 2: Storage
Leave all four stores set to RocksDB (the default). RocksDB is Stalwart’s embedded database and requires no external database server. For a single-node deployment handling up to a few hundred mailboxes, RocksDB performs well without any tuning.
Wizard Step 3: Account Directory
Select Internal Directory. This stores user accounts inside Stalwart itself and lets you manage them through the web admin. If you later need LDAP or OIDC single sign-on, you can migrate to an external directory without reinstalling.
Wizard Step 4: Logging
Select Log File for a bare-metal or VPS deployment. This writes rotating log files under the data directory. For containerized deployments, select Console instead, so Docker or Kubernetes can capture the output.
Wizard Step 5: DNS Management
Select Manual DNS Server Management unless you use Cloudflare, AWS Route 53, or Google Cloud DNS, which Stalwart can manage automatically. With manual mode, Stalwart generates a full DNS zone file you can copy into your provider’s panel.
After completing the wizard, Stalwart prints a permanent admin email and password on the final confirmation screen. Write both down immediately. This password is displayed only once.
Restart the Service
sudo systemctl restart stalwart
After the restart, the admin panel moves to:
https://mail.yourdomain.com/admin
The HTTP port 8080 address will no longer work for sign-in after this point.
Step 5: Configure UFW Firewall and Add DNS Records
Open Required Mail Ports
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp # SSH
sudo ufw allow 25/tcp # SMTP inbound from other mail servers
sudo ufw allow 443/tcp # HTTPS for web admin, JMAP, and ACME
sudo ufw allow 465/tcp # SMTPS with implicit TLS
sudo ufw allow 587/tcp # SMTP submission with STARTTLS
sudo ufw allow 993/tcp # IMAPS
sudo ufw enable
sudo ufw status verbose
Why block port 8080 after setup? The bootstrap admin panel runs over plain HTTP. Leaving port 8080 open on a public IP exposes admin credentials to anyone capturing traffic on the path between you and the server. Block it after you confirm the HTTPS admin panel works.
Why port 465 over 587? Port 465 uses implicit TLS, meaning the connection is encrypted from the first byte. Port 587 uses STARTTLS, which starts unencrypted and upgrades. Implicit TLS (465) is the safer choice for email clients.
Add SPF, DKIM, and DMARC Records
Go to Management > Domains > your domain > View DNS Zone file in the web admin. Stalwart generates all required records. Add these to your DNS provider:
SPF (TXT record on @):
"v=spf1 mx ~all"
Use ~all (softfail) initially, not -all (hardfail). This lets messages reach the spam folder rather than being rejected outright while you confirm all your sending sources are covered. Upgrade to -all once DMARC reports show clean alignment for 2 to 4 weeks.
DKIM: Copy the generated TXT record for stalwart._domainkey.yourdomain.com from the DNS zone file and add it to your DNS provider.
Why 2048-bit DKIM keys? Keys shorter than 2048 bits can be factored with modern hardware. Several major receiving servers now distrust DKIM signatures made with sub-2048-bit keys.
DMARC (TXT record on _dmarc):
"v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; pct=100"
Start with p=none (monitor-only). This collects aggregate reports from Gmail and Outlook showing you who is sending mail as your domain without blocking anything. After confirming clean reports, escalate to p=quarantine then p=reject.
Step 6: Create Mailboxes and Send a Test Email
Add User Accounts
In the web admin, go to Management > Directory > Accounts > Add Account.
Fill in:
- Username and display name
- A strong password
- A storage quota
Why set a quota? Without one, a single mailbox that receives spam or large attachments can consume the entire disk, which fills the mail queue and stops delivery for every other account on the server.
Create an alias for postmaster@yourdomain.com pointing to your admin account. RFC 5321 requires every mail domain to maintain a working postmaster address. Some receiving servers test this, and most abuse reports are delivered there.
Test Delivery and Authentication
Use these three tools to verify your setup works end to end:
- mail-tester.com: Generates a unique one-time address. Send it an email from your new server and get a detailed deliverability score out of 10. A score of 9 or higher means your DNS and authentication are correctly configured.
- MXToolbox SuperTool: Checks your MX, SPF, DKIM, DMARC records, and IP blacklist status from a single interface.
- swaks (SMTP testing tool): Install with
sudo apt install swaksand test authenticated submission:
swaks --to test@gmail.com \
--from you@yourdomain.com \
--server mail.yourdomain.com:587 \
--auth LOGIN \
--tls
Monitor the outbound queue and logs in real time:
sudo journalctl -u stalwart -f
Watch for any 550, 421, or other 4xx/5xx SMTP response codes. A clean test shows 250 2.0.0 Ok: queued and the receiving server accepting the message.
Hardening Stalwart for Production Use
A working mail server and a hardened mail server are not the same thing. These steps close the gaps that attackers routinely probe.
- Block port 8080 in UFW: Run
sudo ufw deny 8080and verify withsudo ufw status. The HTTP admin panel has no place on a production server. - Create role-separated admin accounts: Stalwart supports multiple admin accounts with different permission scopes. Give queue managers only queue permissions, and user admins only user management permissions. If one account leaks, the damage stays contained.
- Never use admin accounts in email clients. Email clients cache credentials locally. An admin password sitting in Thunderbird or Apple Mail is only one client-side compromise away from a full server takeover.
- Verify brute-force protection is active: Stalwart detects and blocks IPs that attempt brute-force logins or account scanning by default. Open the web admin and confirm this setting has not been accidentally disabled after any config changes.
- Set per-account outbound rate limits: Go to WebAdmin > Rate Limiting and configure hourly send limits per account. If one account gets compromised and a spammer starts using it, rate limiting contains the damage and keeps your IP off blacklists.
Troubleshooting Common Issues
Problem 1: Outbound Mail Is Not Being Delivered
Symptom: Messages stay in the queue. No bounce. External servers never receive anything.
Diagnosis:
telnet smtp.gmail.com 25
If the connection hangs, your VPS provider is blocking outbound port 25. This is common on AWS, GCP, and Oracle Cloud.
Fix: Contact your provider and request port 25 unblocking. If they refuse, configure a smarthost relay through WebAdmin > SMTP > Outbound > Relay using a transactional email provider such as Mailgun or SendGrid.
Problem 2: Your IP Is on a Blacklist
Symptom: Receiving servers return a 550 5.7.1 error mentioning a blacklist or policy block.
Diagnosis: Run an MXToolbox Blacklist Check against your server IP.
Fix: Submit delisting requests directly to each blocklist (Spamhaus and SpamCop both have public delisting forms). New VPS IPs from reputable providers are rarely pre-listed, but shared datacenter IP ranges sometimes carry prior history.
Problem 3: DKIM Verification Fails
Symptom: mail-tester.com or a DKIM validator shows a verification failure even though you added the record.
Diagnosis:
dig TXT stalwart._domainkey.yourdomain.com
Fix: Many DNS control panels silently truncate long TXT records or add invisible line breaks. Re-paste the entire DKIM key value as one unbroken string with no spaces or newlines inside the quoted value.
Problem 4: Users Cannot Connect via IMAP
Symptom: Email clients report a connection error or certificate warning on port 993.
Diagnosis:
ss -tlnp | grep 993
sudo journalctl -u stalwart -n 50
Fix: Verify that the TLS certificate Stalwart obtained from Let’s Encrypt matches the exact hostname users are connecting to. A certificate issued for mail.yourdomain.com does not cover yourdomain.com. Also confirm port 993 is open in UFW: sudo ufw status.
Problem 5: Admin Panel Not Reachable After Restart
Symptom: https://mail.yourdomain.com/admin returns a connection error or certificate warning after the first restart.
The ACME certificate request takes one to two minutes after the restart. Stalwart serves a self-signed fallback certificate while the Let’s Encrypt certificate is being issued. Accept the browser warning once, reload after a minute, and the trusted certificate should be in place.
If the page still does not load, verify port 443 is reachable from the internet:
sudo ufw status | grep 443
curl -I https://mail.yourdomain.com/admin
Congratulations! You have successfully installed Stalwart Mail. Thanks for using this tutorial for installing Stalwart Mail server on your Ubuntu 24.04 LTS Linux system. For additional or useful information, we recommend you check the official Stalwart website.