Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mailstack

a tried & true stack config for provisioning self-hosted email.

(i.e. declartitave Postfix + Dovecot for Ubuntu or Debian)

Requirements

The server: a fresh Ubuntu 22.04+ or Debian 11+ VPS, root or passwordless sudo over SSH, 1 GB RAM (2 GB if you enable ENABLE_ANTIVIRUS).

Outbound TCP 25 must be unblocked by your provider, check this before starting.

Stack

Application Role
Postfix MTA. Virtual domains, submission on 587/465, sender-login enforcement
Dovecot IMAP, optional POP3, Maildir, LMTP delivery, file-backed users
rspamd DKIM signing and verification, spam scoring, SPF, DMARC
Redis Backs rspamd's Bayes classifier, greylisting and rate limits
ClamAV Antivirus scanning, driven by rspamd (optional, off by default)
certbot TLS, one certificate per mail host, selected by SNI
nginx Autoconfig/Autodiscover and optional MTA-STS (optional, default on)
fail2ban Mail jails (optional, default on)
UFW Mail port rules, added only when UFW is already active

Install

git clone https://github.com/crnst8/mailstack.git
cd mailstack
ln -s "$PWD/bin/mailstack" /usr/local/bin/mailstack   # optional

Setup

1. Configure

mailstack init

Writes mailstack.conf in the current directory.

2. Check

mailstack check

Verifies: server reachable and supported, outbound port 25, hostname A record, reverse DNS, inbound ports, and warns if a domain still routes mail elsewhere.

3. Publish DNS (Cloudflare)

mailstack dns show      # print the records
mailstack dns apply     # or let Cloudflare do it
mailstack dns verify    # confirm they resolve

Each domain needs an A record for its mail host, MX, SPF, DMARC, a DKIM key, and optional SRV records for autodiscovery.

Reverse DNS is not managed in this setup. Set the PTR for your server's IP to your mail hostname in your VPS provider's control panel.

4. Deploy

mailstack deploy

Installs packages, writes configuration, generates DKIM keys, requests certificates, and starts everything. Run this again when changing configs.

5. Create a mailbox

mailstack user add you@example.com

Point a mail client at mail.example.com, IMAP 993 and SMTP 465.

Usage

mailstack status                 # services, certificates, queue
mailstack audit                  # full health and deliverability check
mailstack user list
mailstack user passwd you@example.com
mailstack domain add example.org && mailstack deploy
mailstack cert renew

mailstack audit checks for open relay, TLS posture, DKIM/DNS agreement, certificate expiry, blocklist listings, PTR mismatch, and a stuck queue. Exits non-zero on anything blocking, so it works in cron.

Moving to another server

mailstack migrate --from root@old-server

Snapshots the old server (delivery pauses briefly), provisions the new one from your config, and restores mailboxes, credentials, DKIM keys and certificates. DNS is unchanged and nothing on the old server is deleted.

Snapshot and restore separately:

mailstack snapshot backup.tar.gz
mailstack restore backup.tar.gz        # --full for a byte-for-byte clone

Restore brings across state only (mail, passwords, keys, certs) leaving the new host's freshly generated configuration in place.

Configuration

Everything lives in mailstack.conf. See examples/mailstack.conf for the full list, or run mailstack config to print current values.

Setting Default
DOMAINS Space-separated mail domains
MAIL_HOSTNAME SMTP hostname; needs a matching PTR
DNS_PROVIDER manual manual or cloudflare
ENABLE_ANTIVIRUS no Adds ClamAV, which needs ~1.1 GB RAM on its own
HOST_MODE coexist coexist or dedicated
DMARC_POLICY none none, quarantine or reject

Cloudflare

Create a token at dash.cloudflare.com → My Profile → API Tokens with Zone → DNS → Edit and Zone → Zone → Read, scoped to the zones you manage. Put it in the config or, better, keep it out:

CLOUDFLARE_API_TOKEN_CMD=pass show cloudflare/dns

With Cloudflare configured, certificates use the DNS-01 challenge, so renewal works even if port 80 is closed.

Security notes

  • Snapshots contain mailbox password hashes, private DKIM keys, TLS keys and all mail. They are mode 0600 and not encrypted, encrypt them at rest.
  • The Cloudflare token is copied to the server only when the ACME DNS challenge needs it.
  • mailstack does not enable UFW. It only adds rules to an already-active UFW.
  • System accounts cannot log in to IMAP; Dovecot uses a dedicated passwd-file.

Troubleshooting

Mail goes to spam. Run mailstack audit first. Usually PTR, DKIM, or a new IP with no sending reputation.

Certificates fail to issue. The name must resolve to the server and port 80 must be reachable, or use Cloudflare DNS-01.

outbound TCP 25 is blocked. Ask your provider to open it.

rspamd will not start. Check rspamadm configtest, then the journal. A common cause is a config file the daemon cannot read: it runs as _rspamd, while configtest runs as root and will pass files the daemon cannot open. Set ENABLE_ANTIVIRUS=no, then mailstack deploy.

See docs/troubleshooting.md and docs/deliverability.md for more.

Licence

MIT.

About

tried & true email server stack

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages