1. Blog
  2. Manuals

Mailcow: Your Own Mail Server on a VPS

Mailcow: Your Own Mail Server on a VPS

Mailcow is a ready-made mail server in Docker containers. It combines Postfix, Dovecot, the Rspamd spam filter, antivirus, SOGo webmail and an admin panel into one system that installs with a few commands and updates with a single script. It is the easiest way to get full-featured mail on your own domain without assembling a dozen services by hand.

Before installing: what to check

A mail server is more demanding than an ordinary site. Check in advance:

  • Resources. At least 6 GB of RAM and 20 GB of disk. With less, you have to disable the ClamAV antivirus. Pick a suitable VPS plan.
  • Port 25. Many providers block outgoing port 25 by default to fight spam. Ask your hosting support about it before installing.
  • Reverse DNS (PTR). The server’s IP address must resolve to the mail server’s name. The PTR record is set on the hosting side — usually in the control panel or by a support request.
  • A clean IP address. Check the address against blocklists, for example on mxtoolbox.com.
  • A clean system. No other mail or web servers may occupy ports 25, 80, 443, 587, 993.

Step 1. DNS records

Say the mail domain is example.com, the server will be called mail.example.com, and its address is 203.0.113.10.

Type Name Value
A mail 203.0.113.10
MX @ mail.example.com (priority 10)
CNAME autodiscover mail.example.com
CNAME autoconfig mail.example.com
TXT @ v=spf1 mx -all

The PTR record for 203.0.113.10 must point to mail.example.com. The DKIM and DMARC records are added after installation.

Step 2. Prepare the server

Install Docker and Docker Compose following the guide. Check the time and time zone — message timestamps depend on them:

timedatectl

Open the ports in the firewall:

sudo ufw allow 25,80,443,465,587,993,995,4190/tcp

Step 3. Installation

Run the commands as root:

su
umask 0022
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized

Generate the configuration:

./generate_config.sh

The script asks for the mail server’s fully qualified name — enter mail.example.com — and the time zone. The result is saved in mailcow.conf. With less than 6 GB of RAM the script offers to disable ClamAV.

Pull the images and start the system:

docker compose pull
docker compose up -d

The first start takes a few minutes. A Let’s Encrypt certificate for mail.example.com is issued automatically.

Step 4. First login

Open https://mail.example.com and log in to the admin panel with the login admin and password moohoo.

Step 5. Domain and mailboxes

  1. Open the mail setup section and go to the Domains tab.
  2. Click Add domain, enter example.com and click Add domain and restart SOGo.
  3. On the Mailboxes tab click Add mailbox and set the mailbox name and password.

Users log in to SOGo webmail at https://mail.example.com/SOGo.

Step 6. DKIM and DMARC

Without these records your messages land in spam.

DKIM. In the admin panel open the DKIM key settings (ARC/DKIM keys), select the domain, a key length of 2048 bits, and click Add. Copy the resulting value into a TXT record:

Type Name Value
TXT dkim._domainkey v=DKIM1;k=rsa;t=s;s=email;p=...

DMARC. Start in monitoring mode:

Type Name Value
TXT _dmarc v=DMARC1; p=none; rua=mailto:postmaster@example.com

After a couple of weeks, once the reports confirm that legitimate mail passes the checks, change the policy to p=quarantine and then to p=reject.

The domain list has a DNS button: it shows which records Mailcow expects and which of them are already set up correctly.

Step 7. Test

Send a message to the address provided by mail-tester.com and look at the score: it reveals problems with SPF, DKIM, PTR and blocklists. The goal is 10 out of 10.

Test the other direction as well: send a message to the new mailbox from an external address.

Connecting mail clients

Protocol Server Port Encryption
IMAP mail.example.com 993 SSL/TLS
SMTP mail.example.com 465 SSL/TLS
SMTP mail.example.com 587 STARTTLS

The login is the full email address. Thanks to the autodiscover and autoconfig records, most clients detect the settings automatically.

Updating

cd /opt/mailcow-dockerized
./update.sh

The script updates Mailcow itself and the container images and applies configuration changes. Run it regularly: security fixes are critical for a mail server.

Backups

A backup script is included:

cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/var/backups/mailcow ./helper-scripts/backup_and_restore.sh backup all

Copy the resulting directory off the server — for example with rclone or to backup storage. Schedule it with cron.

Moving mail from an old server

Mailcow has a built-in synchronisation tool: add a Sync job in the mailbox settings with the old server’s address, login and password. Messages are copied over IMAP. How it works is explained in the imapsync migration guide.

If mail does not arrive

  • Messages are not sent. Check whether outgoing port 25 is blocked: nc -vz gmail-smtp-in.l.google.com 25.
  • Messages land in spam. Check the PTR record, SPF, DKIM and the IP reputation with mail-tester.com.
  • No certificate was issued. The mail A record must point to the server, and port 80 must be open.
  • Logs. The admin panel has a section with the logs of every service; from the shell use docker compose logs --tail=100 postfix-mailcow.

Should you host your own mail

Your own mail server gives full control over the data and unlimited mailboxes, but it needs attention: updates, watching the IP reputation, reading DMARC reports. If mail is business-critical and nobody is there to administer it, consider a hosted mail service — and keep Mailcow for projects where control matters more than convenience.