Skip to content

Start here

There are four things to do, and the first is the only one that can go wrong in a way that costs you an afternoon.

This is the step people skip, and it is the one that decides whether any of the rest works.

  • Outbound port 25 must be open. Most providers block it by default and will open it if you ask — DigitalOcean, Hetzner, Vultr and Oracle all do. AWS and Google Cloud make it hard on purpose.
  • You must be able to set reverse DNS on the IP address, to the same hostname you will use. A mismatched or missing PTR is the single most common reason self-hosted mail is filtered.
  • A fresh Debian 12 or Ubuntu 22.04+ host with a public IPv4, at least 2 GiB of RAM and 10 GiB of disk. Fresh matters: the stack publishes eleven ports — 25, 80, 110, 143, 443, 465, 587, 993, 995, 4190 and 8081 — and they must be free. From 0.11.0 the preflight checks all eleven; 0.10.0 and earlier check only seven (25, 80, 443, 465, 587, 993, 995), so on those a taken 110, 143, 4190 or 8081 passes its checks and then fails.

Point an A record at the host — mail.example.com — before you go any further, and set the PTR at your provider to the same name.

Add two more names, also at the host: postmaster.example.com for the admin console and webmail.example.com for the mail client — A records to the same address, or CNAMEs to mail.example.com. They are built from your hostname with its first label dropped, so a hostname of mx.example.co.uk means postmaster.example.co.uk and webmail.example.co.uk. There is one pair for the whole server, whichever domains it hosts. Their certificates are issued the first time each name is visited, so the records have to resolve by then. The wizard does not list these two, so add them now.

Terminal window
curl -fsSL https://get.maildock.app/install.sh | sh -s -- --hostname mail.example.com

It installs Docker and mailctl if they are missing and checks the preconditions above. It refuses to go on without Docker and Compose, with less than 2 GiB of RAM, or with one of the ports it checks already taken. The public IP, the A and PTR records, outbound port 25 and free disk are only warnings — it prints them and carries on, so read them. Then it brings the stack up and prints the address of the Setup Wizard. Roughly five minutes on a small VPS, most of it pulling images.

Doing this without a browser — for a provisioning script — is

the answers file, which produces byte-for-byte the same result. The full reference, including every error the preflight can print, is the install run-book.

Open the address it printed. The Setup Wizard takes seven steps — hostname, TLS, your first domain, the owner account, AI (skippable), apply, and then the DNS records to publish.

Publish the records before you send anything. The wizard lists SPF, DKIM, DMARC and MTA-STS ready to paste; once you sign in, Verify now on the domain page checks them live. Mail sent from a domain whose records are not yet published is mail that teaches a receiver to distrust you.

Add a mailbox in the admin console — from now on at https://postmaster.example.com — then open https://webmail.example.com and sign in as it. https://<your hostname>/mail still works, as a redirect to the webmail name, so it fails if that record is missing. Desktop and mobile clients configure themselves — MailDock serves

autoconfig and autodiscover, so Thunderbird, Apple Mail and Outlook need the address and the password and nothing else.

  • Moving mail in from somewhere else — migration has a connector for cPanel, Plesk, Google Workspace, Microsoft 365 and plain IMAP, and syncs the delta after you change the MX record so nothing is lost in the cutover.
  • Check your own deliverability before you rely on it. Send to a few addresses at the providers your recipients actually use, and read mail going to spam if any of it lands wrong — it is written in order of likelihood.
  • Set up a backup. mailctl backup is one command and the product does not ship it anywhere for you: backup and restore.
  • Run mailctl doctor once now, so you know what healthy looks like on this machine.

mailctl doctor first — it checks the host, the containers, the database, the daemons and the DNS, and its output is the thing to have in hand. What each check means.