Skip to main content

Going to Production: Hardware Sizing and Domain DNS

Quick Start gets the system running; this guide covers two things you must do before production: choosing the right server, and setting up the DNS records for your mail domain.

Hardware and System Requirements

OS and Software

  • Production deployment: a Linux server (x86_64 / aarch64 both fine) with Docker (Compose v2). All four production stacks (ce / ee / multi / ha) are fully containerized and managed by mailezctl; the distribution's install.sh also offers an interactive installer (pre-checking Docker, Compose v2, openssl, curl).
  • Development experience: the engine and control plane run natively on Linux / macOS / Windows with no restrictions on the dev machine; the Go toolchain (1.26+) is only needed when building images from source.
  • Time sync: enable NTP. The lease mechanism of multi-instance HA / multi-active clusters is sensitive to clock skew; keep single-node deployments time-synced too (scheduled sending and log troubleshooting rely on accurate clocks).

Sizing

The mail stack itself is light: a single Mailezine engine instance idles at about 24 MiB of memory and peaks around 34 MiB under a 10k-user load model (internal benchmark). The bulk of system resources goes to the control plane and infrastructure components (MySQL, TiDB, Rspamd, MinIO). The table below lists recommended starting points — pick a stack by mailbox count:

ScenarioStackvCPUMemoryDisk (SSD)
Personal / trial / demodev or ce1–22 GiB20 GB
Small team (≤ 50 mailboxes)ce24 GiB100 GB
Mid-size org (≤ 500 mailboxes)ce or ee, single node48–16 GiBsized by quota
Scale-out (ee + multi/ha)components on separate nodes4+ per node8 GiB+ per nodesized by quota

Disk estimation: each mailbox defaults to a 1 GiB quota (adjustable per user or per domain in the admin console), plus headroom for full-text search indexes, logs, and attachment staging. Large message blobs and cloud-drive files should land in MinIO/S3 object storage (Enterprise), keeping only hot data on local disk.

Network and Ports

The server needs a public IP with the following ports open:

PortPurposeExposure
25SMTP (server-to-server inbound)inbound public; outbound see below
465 / 587Client sending (SMTPS / Submission)public (for mail clients)
110 / 995POP3 / POP3Spublic (if using POP3)
143 / 993IMAP / IMAPSpublic (for mail clients)
4190ManageSieve (filter sync)public (if clients manage Sieve)
80 / 443Gateway: web entry + ACME auto certificatespublic
8081 / 8082 / 8083Backend API / admin console / webmailinternal only or behind the gateway reverse proxy; do not expose directly

Cloud providers usually block outbound port 25 by default (anti-spam): either request an unblock from your provider, or configure an external SMTP relay (smarthost, SASL auth supported) in the admin console so outbound mail is delivered through the relay; for forwarding scenarios the engine rewrites envelopes with SRS automatically, so bounces never return to your domain.

Domain DNS Setup

Using mail domain example.com and mail host mail.example.com (i.e. MAILEZ_HOSTNAMES) as an example. All records are added at your DNS provider:

TypeHostValuePurposeRequired?
A / AAAAmailserver public IPhost name clients connect to and MX points to; also required for ACME issuance✅ required
MX@mail.example.com (priority 10)routing rule for other servers delivering *@example.com✅ required
TXT (SPF)@v=spf1 a mx -alldeclares "only this host may send for me"; receivers use it to prevent spoofing✅ strongly recommended
TXT (DKIM)<selector>._domainkeyv=DKIM1; k=rsa; p=<public key>outbound signing public key; generate in the admin console and copy the full record✅ strongly recommended
TXT (DMARC)_dmarcv=DMARC1; p=quarantine; rua=mailto:postmaster@example.comtells receivers what to do when SPF/DKIM fails and where to send reports✅ strongly recommended
PTR (rDNS)server IPmail.example.comreverse DNS; set at your cloud/ISP provider, not the DNS provider⭐ strongly affects deliverability
CNAME (optional)autodiscovermail.example.comEnterprise Outlook / Exchange ActiveSync autodiscoveryoptional

Notes:

  • DKIM: generate the key in the admin console under "Domains → DKIM"; the page shows the exact record name and value, ready to copy into DNS. The selector defaults to dkim (changeable via MAILEZ_DKIM_SELECTOR), so the record looks like dkim._domainkey.example.com. Regenerating rotates the key (in-flight mail during the switch window may fail DKIM — expected).
  • SPF: a mx covers both sending paths (mail host A record + MX target); if you also send through a relay provider, append include: per their docs. On the inbound side, the engine runs full SPF / DKIM / DMARC verification on every incoming message and emits Authentication-Results, regardless of whether you publish these records — publishing them protects the mail you send out.
  • PTR reverse DNS: most receivers' anti-spam systems (including mailezine's built-in reputation scoring) check that the sending IP's PTR matches the EHLO host name. Mail from a public IP without a PTR easily lands in spam; configure it in your cloud console before going live.
  • TLS certificates: with MAILEZ_TLS=letsencrypt the gateway obtains and renews certificates automatically (requires 80/443 reachable and the mail.example.com A record in effect); you can also place your own cert.pem / key.pem (see the repo's deploy/certs/README.md). Implicit TLS on 465/993/995 reuses the same certificates.
  • Verification: after saving records, confirm they have propagated globally with dig / nslookup (dig MX example.com, dig TXT dkim._domainkey.example.com); the admin console's DKIM status turns verified once DNS propagates. Then exchange a test message with an external mailbox (Gmail, QQ Mail, etc.) and check the Authentication-Results the recipient shows: spf=pass dkim=pass dmarc=pass. An online mail health-check service works well for a comprehensive audit too.

Production Checklist

  • Server meets the sizing guidance, NTP enabled, Docker + Compose v2 ready
  • Public IP ready, outbound 25 unblocked or relay configured
  • mailez.env sets MAILEZ_SECRET_KEY / MAILEZ_STACK_SECRET / MAILEZ_DOMAIN / MAILEZ_HOSTNAMES (production refuses placeholder secrets)
  • DNS: A / MX / SPF / DKIM / DMARC in effect, PTR configured at the cloud provider
  • Ports: mail ports open to the public, admin ports not exposed
  • TLS: MAILEZ_TLS=letsencrypt (or your own certs), implicit TLS handshakes on 465/993/995
  • Admin account created (mailez-seed), default password changed
  • Backups: config export + engine backup (full KV+blob export) in routine ops
  • Enterprise: MAILEZ_LICENSE_FILE mounted, license shown as valid on the overview page

For scale-out operations details see the repo's docs/scaling.md; upgrade procedures are in docs/upgrades.md and docs/rollout-runbook.md.