Skip to content

Installing MailDock on Hetzner Cloud

Hetzner blocks outbound port 25 on new accounts and will unblock it on request. Everything else about running mail here is straightforward and cheap.

Hetzner is where a lot of self-hosted mail lives, for the obvious reason: a CX22 with 2 vCPU and 4 GiB is a few euros a month, which is more machine than a mail server for a few dozen mailboxes needs.

Before you create the server

Ask for port 25 first. The ticket takes a day and the install takes ten minutes; doing them in that order saves you a day. Say what the server is for — “mail for my own domains”, “mail for my clients” — and that you are not sending bulk or marketing mail, because that is the thing they are screening for.

Sizing

A CX22 (2 vCPU, 4 GiB, 40 GB) is comfortable. The floor is 2 GiB of RAM and 10 GB of disk, and disk is the one to think about: it holds everybody’s mail and grows for ever.

Location matters for two reasons. Latency, obviously — but also jurisdiction, which for a mail server is a real decision rather than a preference. Nuremberg, Falkenstein and Helsinki are EU; Ashburn and Hillsboro are US; Singapore is Singapore.

IPv6

Hetzner gives every server an IPv6 /64, and the Cloud Firewall lets IPv6 through unless you say otherwise.

From 0.8.0 MailDock can serve IPv6, and it is off until you switch it on. Until you do, publish no AAAA record for any name this server answers — not the mail hostname, and not webmail., postmaster. or any domain you point here later: with IPv6 off nothing answers there, so mail servers and certificate challenges that prefer IPv6 fail. Keeping inbound IPv6 closed in the provider’s firewall stays sensible while it is off.

To serve IPv6, install with mailctl install --ipv6, or set IPV6_ENABLED=true in /opt/mailserver/.env and run npm i -g @maildock/mailctl@latest && mailctl upgrade — the CLI first, because an older one has no IPv6 override to apply. It needs Docker 27 or later, which forwards IPv6 so that each client keeps its own address — on an older Docker an IPv6 client would look like the server itself and could relay mail without signing in, which is why the installer refuses it. Then:

  • run mailctl doctor and wait for its ipv6 row to read ✔;
  • open the mail and web ports to IPv6 in the provider’s firewall;
  • publish an AAAA record for the mail hostname, and set the reverse DNS (PTR) for the server’s IPv6 address in the provider’s console;
  • outbound mail stays on IPv4 unless you turn outbound IPv6 on, which MailDock refuses until that PTR is in place.

The details are in the IPv6 page of the docs.

Then the ordinary install

Everything from here is the standard install: point an A record at the server, along with postmaster. and webmail. of the same domain, set the PTR to the mail hostname, run the one command, and publish the DNS records the wizard generates.

Checked against Hetzner’s own documentation on . Providers change their policies without telling us — tell us if this is out of date. Sources: Hetzner Cloud documentation