Tech Digest

Category

Chat, mail and notifications: what is worth self-hosting and what is not

One thing in this category costs 30 MB and works forever. Another can silently stop delivering your mail to Gmail and give you no way to earn the reputation back.

6 tools profiledMedian idle memory 500 MBLast reviewed

Self-hosted mail is a reputation problem wearing a software costume#

Every guide to self-hosted mail is written as though the difficulty is configuring Postfix. It is not. mailcow: dockerized and Stalwart both solve the software problem completely, and neither touches the actual one.

Answer three questions before you install anything. Can you open outbound port 25? Most residential ISPs block it, and several major clouds block it by default. Can you set a PTR record that matches your mail hostname exactly, for IPv4 and IPv6 both? That is a control panel setting at whoever owns the IP block, not a record in your DNS zone, and a mismatch is the most common reason a correct mail server is rejected by Outlook and Gmail. Is your IP range already on the usual blocklists? A fresh address has no sending reputation, which means weeks of greylisting even when everything is right.

If any answer is no, stop. And understand the failure mode you are signing up for, because it is not an outage. Your stack stays green, your logs stay clean, and your mail is silently discarded at the far end. You learn about it when a customer says they never received the invoice. Reputation is earned by sending volume over time and cannot be purchased back.

Who should still do it#

Someone with a static IP, a PTR record they control, and a business reason: leaving Microsoft 365 for cost or jurisdiction, or wanting SOGo webmail, calendar and contacts on the same box as IMAP. That person should run mailcow, budget the documented 6 GiB plus 1 GiB of swap and 20 GiB of disk before any mail exists, and back up the crypt volume in the same run as vmail, because Dovecot's mail-crypt keys live in crypt and a vmail backup without them restores as unreadable ciphertext.

Everyone else should take the hybrid: host receipt, filtering and storage, relay outbound through Postmark, SES or Mailjet. You keep your archive on your disk and hand the unwinnable part to someone whose full-time job it is.

The default#

Start with notifications, because they are the genuinely good part of this category. ntfy is one container, roughly 30 MB idle, and curl -d "backup done" https://ntfy.example.com/alerts is the entire integration for cron jobs, Uptime Kuma, Home Assistant and your backup scripts. It has an official iOS app, which is the deciding fact for most households.

Two situations where that is the wrong pick. Android-only, and you want per-sender revocation: Gotify gives every sender its own application token in 20 MB, where ntfy's model is that the topic name is the credential. You need a chat server, not alerts: Mattermost for a private team on PostgreSQL 14 or newer, Synapse only if federating with other people's servers is the actual requirement.

The mistakes#

  • Leaving ntfy at its defaults. A fresh install has no authentication and auth-default-access is read-write, so every topic on your server is world-readable and world-writable. Set deny-all and grant with ntfy access before you point a door sensor at it.
  • Gotify's admin/admin. GOTIFY_DEFAULTUSER_* is read only when the first user is created, so setting it later does nothing and people assume they are covered.
  • Upgrading Debian 12 to 13 under mailcow. It can pull in Exim, which binds port 25 and stops Postfix accepting inbound mail. Check ss -lntp | grep :25 after any host distribution upgrade.
  • Creating Synapse's database without --locale=C --template=template0. Synapse refuses to start, or you set allow_unsafe_locale and get subtly wrong string ordering that surfaces later as missing events.
  • Serving Matrix on 443 without /.well-known/matrix/server. Your own clients work perfectly while no other homeserver can reach you. The symptom is invitations that never arrive.
  • Assuming Mattermost history is safe. The Entry edition's 10,000 message limit is server-wide and silent: older posts stay in the database and stop being searchable.

ntfy vs Gotify settles the push decision in detail, and mailcow vs Stalwart the mail one. Replace Gmail walks the hybrid migration, Replace Slack the chat one. Before you commit to mail at all, read When not to self-host and DNS for self-hosters, in that order.

Every communication tool we profile#

Sorted by operational load, lightest commitment first. Every row links to a full profile with the resource numbers, the upgrade traps and the restore path.

ToolOps loadIdle RAMLicenceIdentityBackup shape
Gotify1, Set and forget20 MBMITNative OIDCSQLite backup
ntfy1, Set and forget30 MBApache-2.0 (dual licensed with GPL-2.0)Local accounts onlySQLite backup
Mattermost3, Moderate500 MBAGPL-3.0 core, Mattermost Source Available License for `server/enterprise/`, Apache-2.0 for webapp and admin tools, MIT for official binariesNative OIDCPostgres dump
Stalwart3, Moderate150 MBAGPL-3.0 for the Community edition, dual licensed with the proprietary Stalwart Enterprise License for gated featuresLDAP onlyEmbedded key-value store
Synapse4, Heavy700 MBAGPL-3.0-only (or a commercial license from Element)Native OIDCPostgres dump
mailcow: dockerized4, Heavy3500 MBGPL-3.0 for mailcow's own code; bundled components keep their own licensesNative OIDCMySQL dump

Profiles#

Head to head in this category#

Leaving a cloud service in this category#

Questions#

Can I self-host email on my home connection?

Almost certainly not for outbound. Most residential ISPs block outbound port 25, several major cloud providers block it by default, and you cannot set a PTR record for an address you do not own, which is a control panel setting at whoever holds the IP block. A missing or mismatched PTR is the single most common reason a technically perfect mail server gets rejected by Outlook and Gmail. Receiving mail is genuinely easy. Sending it so that it lands in an inbox is the entire job, and no software in this category changes that.

What happens when self-hosted mail stops working?

Usually nothing visible. Your stack stays green, your logs look fine, and messages you send are quietly binned or greylisted at the far end. You find out days later when someone says they never got it. The recovery is slow because sending reputation is earned by volume over time and cannot be bought back. This is the argument for the hybrid shape: run receipt, filtering and storage yourself, and relay outbound through Postmark, SES or Mailjet so a reputation problem is somebody else's full-time job.

mailcow or Stalwart?

mailcow is 18 containers (Postfix, Dovecot, Rspamd, ClamAV, SOGo, MariaDB, Redis and the rest) with a documented minimum of 6 GiB plus 1 GiB swap and 20 GiB of disk before any mail arrives. Stalwart is one Rust binary covering SMTP, IMAP, JMAP, CalDAV and CardDAV, idling near 150 MB. Pick mailcow for the best-documented path and a UI that manages DKIM, aliases and quotas. Pick Stalwart if 18 containers is absurd for one domain, and check the Enterprise split first: third-party OIDC login, multi-tenancy and deleted-mail recovery are paid.

ntfy or Gotify?

ntfy for most households. curl -d "backup done" ntfy.sh/mytopic works with no account and no token, there is an official iOS app, and you can start on the hosted instance and move to your own server without changing a publish call. Gotify is stricter and smaller: 20 MB, every sender gets a revocable application token, nothing is readable without one. Gotify has never had an official iOS app and there is no hosted instance holding an Apple push certificate, so if anyone in the house uses an iPhone that decision is already made.

Does self-hosted push actually work on an iPhone?

With ntfy, yes, with one caveat. Apple only delivers push through APNs and your server has no APNs certificate, so you set upstream-base-url: "https://ntfy.sh". Your server then publishes a poll_request containing only a message ID to ntfy.sh, which wakes the app through APNs, and the app fetches the body from you. Without that setting, notifications arrive 20 to 30 minutes late or worse. The message body never transits a third party, but the wake-up does, and the maintainer describes the iOS app as bare bones.

Should I run Matrix or Mattermost for team chat?

Run Synapse only if you specifically want federation with other servers. If you want private team chat, it is the wrong shape of work: room state, not messages, dominates the database, and the project's own tracker has reports of state_groups_state reaching 274 million rows and 51 GB. Schedule synapse_auto_compressor from day one. Mattermost gives you Slack's shape on PostgreSQL 14 or newer, but from v11 Team Edition is capped at 250 activated users and lost GitLab SSO, so free now means local accounts.

Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.