Mailu is a Docker Compose stack of standard parts: Postfix, Dovecot, Rspamd, an admin interface, and webmail. You do not write the Compose file yourself, because a wizard on their site generates it from your answers.
1. Before you start
Port 25 must be open, reverse DNS must point at your mail hostname, and your DNS must be yours to edit. Our guide on what running your own mail server actually takes covers all of it.
You also need Docker installed, and 2 to 3 GB of RAM is a realistic floor.
Mailu wants ports 80, 443, 25, 465, 587, 110, 995, 143, 993, and 4190 on the host. If this server already runs a website, that conflicts on 80 and 443. Give mail its own server unless you are prepared to do the reverse proxy work.
2. Pick the right version
Mailu's version naming is unusual, and choosing the wrong one is a common way to end up running development code in production:
- A dated branch such as
2024.06is the stable release, and it keeps receiving patches. This is what new setups should use. X.Y.Zpins to a specific commit, so containers never change under you when they are recreated. Use this if you want to control exactly when you update.latestpoints at the master development branch. Their documentation says plainly you should never use it for a production server.
Check their setup site for the current stable version. Do not copy a number out of any guide, including this one.
3. Run the wizard
Go to setup.mailu.io and pick the current stable version. The wizard asks for your mail hostname, your domain, which optional features you want (webmail, antivirus, fetchmail, and so on), and the IP addresses the ports should bind to.
When you finish, it gives you a unique URL with two files behind it. Download both onto your server:
$ sudo mkdir -p /mailu && cd /mailu $ wget <the docker-compose.yml URL the wizard gave you> $ wget <the mailu.env URL the wizard gave you>
Both files are generated for your answers, so do not copy them from someone else's guide.
4. Review the environment file
Open mailu.env and check three things before starting:
SECRET_KEYmust be a random 16 character string. The wizard generates one, but confirm it is not left at a placeholder.- The bind addresses must be your server's real public addresses, not
127.0.0.1, or nothing outside the machine can reach your mail server. - The data path,
/mailuby default, is where everything persistent lives. TLS_FLAVORdecides how certificates work.letsencryptobtains them automatically and is what most people want.certmeans you supply them yourself, andnotlsis for testing only.
5. Start it and create the admin
$ cd /mailu $ docker compose up -d $ docker compose logs -f
The first start pulls a lot of images. Once it settles, create the first administrator:
$ docker compose exec admin flask mailu admin me example.com PASSWORDThat creates [email protected] with administration privileges. Then open https://mail.example.com/admin, sign in, and change the password to a strong one.
6. Add your domain and publish DNS
In the admin interface, add your domain, then open its details page. Mailu shows the DNS records it expects, including the DKIM key it generated. Publish them at your DNS provider.
Our DNS records guide explains what each one does.
Mailu ships its own DNS resolver
The stack includes an unbound container that the other services use for lookups. That matters for spam filtering, because DNS blocklists refuse queries from large public resolvers like Cloudflare and Google. Mailu solves that problem for you, which several other platforms leave to you.
7. Spam filtering
Rspamd does the filtering, and Mailu puts the parts most people need in the admin interface:
- A default spam threshold for new users, set globally, with each user able to adjust their own.
- Per-user and per-domain allow and deny lists.
- Greylisting, which temporarily refuses mail from unknown senders.
- Antivirus with ClamAV, which is optional in the wizard. Leaving it off is the single biggest memory saving available.
Rspamd learns from what users do with their Junk folder, so tell your users to move messages into and out of Junk instead of deleting them.
For anything deeper, Mailu supports an overrides directory where you can drop your own Rspamd configuration without editing the generated files.
8. Updating
$ cd /mailu $ docker compose pull $ docker compose up -d
If you pinned an X.Y.Z version, edit that value first. Some releases need docker compose down --remove-orphans in between because of network changes, so read the release notes before each upgrade.
Quick reference
| Task | Command or place |
|---|---|
| Generate config | setup.mailu.io, pick the stable version |
| Data directory | /mailu |
| Create admin | docker compose exec admin flask mailu admin me example.com PASSWORD |
| Admin interface | https://mail.example.com/admin |
| Update | docker compose pull && docker compose up -d |
| Never use | the latest tag in production |
Where to go next
Publish the DNS records from the domain details page, then send a test message in each direction. If you want calendars and contacts, Mailu does not bundle them; our comparison guide covers the platforms that do.