Head to head
mailcow vs Stalwart
Both give you SMTP, IMAP and spam filtering on a domain you own. Which one you pick barely affects whether your mail arrives, and this page is mostly about that.
mailcow or Stalwart?
Run mailcow if you have 6 GiB of RAM to spare and want webmail, calendar and contacts through SOGo with the best documentation in self-hosted mail. Run Stalwart if you want one Rust process instead of eighteen containers, you can live with a pre-1.0 project shipping weekly, and you do not need multi-tenancy, SCIM or login through an external identity provider, all of which are behind its paid Enterprise licence. Neither choice affects whether Gmail accepts your mail, which is the part that actually decides if self-hosted email works for you.
Nothing on this page matters until you can answer three questions#
Self-hosted email is a deliverability problem wearing a software costume. You can install either of these products correctly, watch every service come up green, send a test message, and still have your mail land in a spam folder or vanish into a silent drop for the next six months. The software is not what fails.
Answer these first:
- Can you open outbound port 25? Most residential ISPs block it permanently. Several major cloud providers block it on new accounts and require a support request that is often declined. Port 587 to a relay is not the same thing: 25 is what your server needs to reach Gmail's inbound servers directly.
- Can you set a PTR record that matches your mail hostname exactly? Reverse DNS lives with whoever owns the IP block, so it is a control panel setting at Hetzner, OVH or DigitalOcean, and it does not exist at all for most home connections. The mailcow docs require it for IPv4 and IPv6 both. A missing or mismatched PTR is the single most common reason a technically perfect mail server gets rejected by Outlook.
- Is your address already on the usual blocklists? New cloud IPs are often recycled from a previous tenant who spammed. You inherit their reputation, and there is no appeal process worth the name.
If any answer is no, you have two honest options: do not do this, or run either product with outbound relayed through an SMTP provider and self-host only receipt, filtering and storage. When not to self-host covers the first. The relay section below covers the second. Replace Gmail covers the whole decision in more detail, including whether you should be leaving Gmail at all.
What the spec table decides#
Two rows carry the entire argument. Services to run is 18 against 1. Idle memory is 3500 MB against 150 MB, and mailcow's documented floor is 6 GiB plus 1 GiB of swap, not a comfort figure. Everything else follows from those two numbers: what breaks, how you debug it at 3am, and what hardware you need.
| Specification | mailcow: dockerized | Stalwart |
|---|---|---|
| Licence | GPL-3.0 for mailcow's own code; bundled components keep their own licenses (Copyleft) | AGPL-3.0 for the Community edition, dual licensed with the proprietary Stalwart Enterprise License for gated features (Copyleft) |
| Written in | PHP / shell, orchestrating Postfix, Dovecot and Rspamd | Rust |
| First release | 2016 | 2023 |
| Maturity | Mature | Young |
| Datastore | MariaDB 10.11 plus Redis | RocksDB by default; PostgreSQL, MySQL, SQLite, FoundationDB, S3 and Redis also supported |
| Services to run | 18 | 1 |
| Idle memory | 3500 MB | 150 MB |
| Memory in use | 6144 MB | 512 MB |
| Operational load | 4 / 5, Heavy | 3 / 5, Moderate |
| Identity | Native OIDC | LDAP only |
| arm64 builds | Yes | Yes |
| Default ports | 25, 80, 110, 143, 443, 465, 587, 993, 995, 4190 | 25, 110, 143, 443, 465, 587, 993, 995, 4190, 8080 |
| Backup shape | MySQL dump | Embedded key-value store |
Eighteen containers or one binary#
mailcow is an orchestration of things that already worked. Postfix, Dovecot, Rspamd, ClamAV, SOGo, MariaDB 10.11, Redis, nginx, php-fpm, unbound, acme, netfilter, watchdog, dockerapi, memcached, olefy, ofelia and postfix-tlspol come up from one docker compose up -d after generate_config.sh. First release was 2016, and it shows in the best sense: when something breaks, the component that broke has fifteen years of search results behind it. A Dovecot error message is a Dovecot error message, not a mailcow error message.
The cost is coupling. Eighteen containers share mailcow.conf, one MariaDB, and an update path through ./update.sh. You will not debug this at the container level; you will read the docs and follow them. MAILCOW_HOSTNAME is written into certificates, DKIM records, SOGo config and the SMTP banner, and changing it later is not a supported edit. Pick mail.yourdomain.tld and mean it.
Stalwart is the opposite bet. One Rust process is SMTP, IMAP4, POP3, JMAP, CalDAV, CardDAV and WebDAV at once, with RocksDB under /var/lib/stalwart holding messages, blobs, full-text index and accounts together. Two volumes, one config directory, no database service to back up separately. It idles at roughly 150 MB and sits near 512 MB in use, which puts a complete mail and calendar server inside what a single Nextcloud container wants.
The cost is novelty. First release was 2023, it is still 0.16.x in September 2026, and it ships roughly weekly. Point releases inside 0.16.x are a docker pull and restart, but crossing a minor line has documented migration steps and no downgrade path. Falling five minors behind and then jumping is the mistake people make with a project that releases this fast.
One deployment detail catches nearly everyone: the first Stalwart start generates a fallback administrator with a random 16 character password and writes it to stderr exactly once. Start with docker compose up -d, never read the logs, and you cannot finish setup. Then close port 8080, because the management interface stays published until you stop publishing it.
Stalwart's licence, precisely#
Getting this wrong is expensive, so here it is exactly. The Community edition is AGPL-3.0, and self-hosted use is unrestricted, including commercial use. The project is dual licensed: the same binary you pull also contains Enterprise code, unlocked by a key under the proprietary Stalwart Enterprise License.
Behind that key: multi-tenancy, account un-deletion, restoring deleted mail, SCIM provisioning, delivery history, the AI spam classifier, and signing in through a third-party OIDC provider such as Keycloak, authentik or Entra ID.
That last one is the sharp edge for self-hosters. If your plan is to put every service behind one identity provider, as in Single sign-on for self-hosters, mail is the service that will not join for free. Stalwart Community can act as an OIDC provider and authenticate against LDAP, Active Directory or SQL, but it will not accept logins from your existing IdP. mailcow can: identity providers including Keycloak and generic OIDC are configured in the mailcow UI itself, with users created on first login. Mail clients still need app passwords either way, because IMAP does not speak OIDC in any client you actually use.
mailcow's own licence is simpler: GPL-3.0 for mailcow's code, with each bundled component keeping its own.
The two ways your backup turns out to be worthless#
These failure modes are different and both are silent until restore day.
mailcow: the crypt volume. Dovecot stores mail encrypted, and the keys live in the crypt volume, separately from vmail. Back up vmail alone and you restore a perfect maildir tree that nobody can open. Use the official script so the components stay consistent:
cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/mnt/backup ./helper-scripts/backup_and_restore.sh backup allThat covers vmail, crypt, redis, rspamd, postfix and mysql. Keep mailcow.conf alongside it. A live rsync of vmail on its own is fine for maildir files, which are write-once, but MariaDB and Redis need the script's dumps rather than a file copy, for the reasons in Backing up a running database.
Stalwart: RocksDB. The default store is a single RocksDB instance. Rsync /var/lib/stalwart while the server is running and you can capture a partially written write-ahead log that refuses to open, which you discover months later. Stop the container for the copy, take an LVM or ZFS snapshot, or move the store to PostgreSQL and dump it properly. Back up /etc/stalwart too: it holds the DKIM private keys, and losing them means every message signed with the old selector fails verification until you publish new DNS.
Either way, push the result somewhere else with restic or BorgBackup (restic vs BorgBackup if you have not picked), and rehearse the restore. Backups that actually restore exists because mail is exactly the service where nobody finds out until it is too late.
Use an outbound relay, and no, that is not cheating#
The standard objection is that relaying outbound through Postmark, SES, Mailgun or your host's submission service means you are not really self-hosting. That confuses ownership with plumbing.
What you keep: the domain, every mailbox, the entire message archive going back years, your spam policy, your aliases, your calendar and contacts, and the ability to change relay providers in twenty minutes by editing one line. What you rent: reputation on somebody else's IP addresses, which is the one component you cannot manufacture, cannot buy back once damaged, and which took the relay provider years and a compliance team to build.
For mailcow, the supported route is the Routing page in the UI, which writes sender-dependent transports. The underlying Postfix override file works too:
# data/conf/postfix/extra.cf
relayhost = [smtp.provider.example]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = static:apikey:YOUR_TOKEN
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encryptFor Stalwart, the equivalent is a queue routing rule that sends outbound to a named remote host with SASL credentials on 587 instead of delivering directly on 25. Check the current documentation for the key names rather than copying a snippet from a blog post, because a project shipping weekly moves configuration keys between minor lines.
Then publish SPF, DKIM and DMARC for the relay as well as your own host, and point a check at your MX with Uptime Kuma so you learn about a dead mail server from a notification rather than from a colleague. DNS for self-hosters covers the record layout.
Which one for your situation#
| Your situation | Use | Why |
|---|---|---|
| Small business, real customers, static IP with controllable PTR | mailcow | Best-documented stack, webmail and calendar included, ten years of answers online |
| Homelab, mail is a hobby, downtime is survivable | Stalwart | One container, 150 MB idle, config you can read in a sitting |
| A 1 to 2 GiB VPS | Stalwart | mailcow's documented floor is 6 GiB plus swap and it is not negotiable |
| You want webmail, calendar and contacts for a family | mailcow | SOGo ships in the stack and is what non-technical users will actually use |
| You need multi-tenancy, SCIM or deleted-mail recovery | mailcow | Those are Enterprise-only in Stalwart, and no configuration reaches them |
| Mail must log in through your existing OIDC provider | mailcow | Native IdP support in the UI; Stalwart Community cannot consume external OIDC |
| Inbound mail only, outbound relayed | Either | Both do this well; pick on RAM |
| Residential connection, no PTR, port 25 blocked | Neither | Keep a paid provider and read Replace Gmail |
| You want JMAP, or CalDAV from the same server as mail | Stalwart | Both are in the single binary rather than bolted on |
What to do next#
Do the three checks at the top of this page first, in this order: telnet gmail-smtp-in.l.google.com 25 from the box that will send, then confirm your provider's control panel lets you set reverse DNS, then look up your candidate IP on a blocklist checker. That takes fifteen minutes and it decides more than this comparison does.
If all three pass, pick on RAM and appetite for a pre-1.0 project, put the web interfaces behind a reverse proxy (Reverse proxy and TLS, usually Caddy), and harden the host with A security baseline for a home server before mail exists on it. Set the hostname you will still want in three years, because mailcow will not let you change it and moving hosts later means Moving a service to a new machine plus imapsync.
If any check fails, read Replace Gmail before you spend a weekend on this. It makes the case for the middle path, which is owning your domain, paying somebody else to run the mailboxes, and keeping the ability to leave. That is the right answer for more people than either product on this page.
Questions#
Can I self-host email on a home internet connection?
For receiving, usually yes if your ISP lets inbound 25 through and you have a stable address. For sending, almost never. Most residential ISPs block outbound port 25 and will not unblock it, and even where they do, you cannot set the PTR record for an address you do not own, and residential ranges sit on blocklists by default. The workable home setup is inbound mail plus outbound through an authenticated SMTP relay on port 587.
How much RAM does mailcow actually need?
The docs state 6 GiB plus 1 GiB of swap for the default configuration, and that is a minimum rather than a suggestion. ClamAV loading its full signature database and the Flatcurve full-text index account for most of it. Both can be disabled in mailcow.conf if you are on a 4 GiB box, which is a supported choice; running the default eighteen-container stack under-provisioned is not. Stalwart idles nearer 150 MB and sits around 512 MB in use.
Is Stalwart really free for commercial use?
The Community edition is AGPL-3.0 and self-hosting it commercially is unrestricted. The catch is that the same binary contains Enterprise code that a licence key unlocks, so some features exist in the build you are running but will not turn on. Multi-tenancy, account un-deletion, restoring deleted mail, SCIM provisioning, delivery history, the AI spam classifier and signing in through a third-party OIDC provider are all paid. Check that list before you design around a feature.
What is the safest way to back up either one?
For mailcow, run helper-scripts/backup_and_restore.sh backup all so you capture vmail and crypt in the same moment. crypt holds the Dovecot mail-crypt keys, and vmail without it restores as unreadable ciphertext. For Stalwart, do not rsync /var/lib/stalwart while it runs: RocksDB is a live log-structured store and a copied write-ahead log can fail to open. Stop the container, take a filesystem snapshot, or move the store to PostgreSQL and dump it.
Does using an SMTP relay defeat the point of self-hosting mail?
No. You still own the domain, the mailboxes, the message archive, the spam policy and the ability to move providers in an afternoon. What you rent is sending reputation, which is the one component you cannot build yourself on a new IP address and cannot repair once it is damaged. Relaying outbound through a transactional provider on port 587 while keeping receipt, filtering and storage local is the configuration most working self-hosted mail actually runs.
Can I put mail behind my single sign-on provider?
With mailcow, yes: identity providers are configured in the mailcow UI itself, including Keycloak, generic OIDC and LDAP, with users created on first login. Mail clients still need app passwords unless you use the Mailpassword flow. With Stalwart Community you cannot: it authenticates against its internal directory, LDAP, Active Directory or SQL, and accepting logins from an external OIDC provider is an Enterprise feature.
Which is easier to migrate away from later?
Both, equally, because IMAP is the escape hatch. imapsync moves mailboxes between any two IMAP servers, so your exit path from either product is the same command. What is not portable is the surrounding configuration: mailcow's aliases, quotas and Rspamd policy live in MariaDB, Stalwart's live in its config and directory. Budget a weekend for re-entering policy, not for moving messages.
Sources#
- mailcow docs, system prerequisites, RAM and ports
- mailcow docs, DNS prerequisites including PTR
- mailcow docs, backup procedure and components
- mailcow-dockerized repository and license
- Stalwart open source licensing, AGPL and Enterprise split
- Stalwart Community vs Enterprise feature comparison
- Stalwart Docker installation, ports, volumes and bootstrap
- Stalwart releases and upgrade notes
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.