This guide walks through a full production deployment on a dedicated server: installation, DNS authentication, security hardening, and the deliverability testing that actually determines whether your mail lands in the inbox or the spam folder.
Prerequisites
Before you start, make sure you have:
- A dedicated server with a static public IP address, running on KVM or bare metal. Mailcow needs proper kernel-level Docker support (cgroups, overlay filesystems), which container-based virtualization like LXC and OpenVZ generally can't provide — avoid those for the host.
- Minimum resources: 2 CPU cores (4+ for production), 6 GB RAM plus 1 GB swap (8 GB+ recommended), and 40 to 50 GB of storage (SSD preferred).
- A supported OS: Debian and Ubuntu LTS releases are the most heavily tested.
- A clean IP address: Check your server IP against blocklists (Spamhaus, Barracuda, SORBS) before committing to it. If it has a bad reputation, deliverability will suffer regardless of how well you configure the server.
- Port 25 open (Outbound & Inbound): Many cloud/VPS providers block outbound port 25 to curb spam. Confirm with your host that port 25 is unblocked, otherwise SMTP simply won't work. If your provider refuses to unblock it, your fallback is to route outbound mail through a smarthost/relay.
- Reverse DNS (PTR) control: You'll need your hosting provider to set the PTR record for your IP to match your mail server's hostname (e.g., mail.yourdomain.com). If you have both an IPv4 and IPv6 address, both must have a PTR record pointing to this hostname.
Step 1: Prepare the Server
Update the system and confirm the required ports aren't already in use by another service:
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git apt-transport-https ca-certificates gnupg lsb-release
ss -tlpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190'
If anything else is bound to those ports (an existing web server on 80/443, another mail service on 25/587/993), stop or reconfigure it first.
Confirm your system clock is correct and NTP-synced, which is critical for Let's Encrypt TLS certificate validation and TOTP two-factor codes:
timedatectl
Step 2: Install Docker
Mailcow requires recent versions of Docker Engine and Docker Compose. Rather than piping a downloaded script straight into sh, download it first so you can inspect it, then run it:
curl -fsSL https://get.docker.com/ -o install-docker.sh
sh install-docker.sh
sudo systemctl enable --now docker
If you'd rather avoid the convenience script entirely, install Docker Engine and the Compose plugin from Docker's official apt repository per their current documentation for your distribution.
Step 3: Download and Configure Mailcow
Clone the repository and run the configuration script:
sudo mkdir -p /opt && cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd /opt/mailcow-dockerized
sudo ./generate_config.sh
You'll be prompted for two important values:
- MAILCOW_HOSTNAME: The Fully Qualified Domain Name (FQDN) of the mail server itself (e.g., mail.yourdomain.com). This is what your PTR records and Let's Encrypt certificates will be built around.
- MAILCOW_TIMEZONE: Your local timezone (e.g., America/New_York).
This script generates your mailcow.conf file. If your server uses IPv6, ensure enable_ipv6 in Docker is configured correctly, or optionally disable IPv6 in mailcow.conf entirely if your hosting provider does not grant you IPv6 PTR records. (Note: Sending IPv6 mail without a PTR record will result in immediate rejection by Gmail).
Step 4: Start the Stack
Pull the latest container images and bring the stack up:
sudo docker compose pull
sudo docker compose up -d
This starts Postfix, Dovecot, Rspamd, ClamAV, SOGo, MariaDB, Redis, and Nginx. The first boot takes a few minutes while the databases initialize.
Once the logs settle, the admin UI is reachable at https://<your-server-IP-or-hostname>. Mailcow automatically provisions a Let's Encrypt certificate assuming ports 80/443 are reachable.
Step 5: Initial Login and Admin Hardening
Log in to the admin UI using the default credentials:
- Username: admin
- Password: moohoo
Change this password immediately. Navigate to the admin's profile settings and set a complex password. While you're there:
- Enable Two-Factor Authentication (TOTP or WebAuthn/U2F) on the admin account.
- Under System → Configuration, review the Fail2Ban settings and adjust ban thresholds if needed.
Step 6: Configure DNS Records (Authentication)
This step determines whether your mail actually reaches the inbox. You need specific DNS records for every domain you send from. Assuming your server is mail.yourdomain.com, its IPv4 is 1.2.3.4, and its IPv6 is 2001:db8::1:
| Name | Type | Value |
|---|---|---|
| A | 1.2.3.4 | |
| AAAA | 2001:db8::1 | |
| autodiscover | CNAME | mail.yourdomain.com |
| autoconfig | CNAME | mail.yourdomain.com |
| @ | MX | 10 mail.yourdomain.com |
| @ | TXT (SPF) | v=spf1 mx -all |
| _dmarc | TXT | v=DMARC1; p=none; rua=mailto:[email protected] |
Why v=spf1 mx -all? Relying solely on an IP address (e.g., ip4:1.2.3.4) is brittle. By using mx, you authorize whatever IPv4 or IPv6 address your MX record resolves to. The -all dictates a "Hard Fail" for any unauthorized servers.
DKIM: Generate your DKIM key inside the Mailcow UI: Configuration → Mail Setup → Domains → [Select Domain] → Key Icon. Mailcow will generate the exact TXT record you need to publish. Raw DNS zone files automatically split values over 255 characters into quoted chunks, which is standard — but some DNS provider web panels don't do this for you. If your panel rejects the long string or truncates it, you'll need to manually break it into quoted 255-character segments yourself.
Once published, check the DNS button in Mailcow. Mailcow parses your live DNS zone; when properly configured and propagated, your A, MX, SPF, DKIM, and DMARC records will all light up with green checkmarks.
Step 7: Add Your Domain and Mailboxes
- Add Domain: Go to Configuration → Mail Setup → Domains → Add Domain. Enter the bare domain (yourdomain.com).
- Add Mailbox: Go to Configuration → Mail Setup → Mailboxes → Add Mailbox. Set the username, password, and allocate a quota.
Step 8: TLS Certificates
Mailcow handles TLS certificate generation and renewal automatically via its acme-mailcow container. It secures the primary hostname and any ADDITIONAL_SAN domains defined in mailcow.conf.
If you prefer to use a custom commercial certificate, set SKIP_LETS_ENCRYPT=y in mailcow.conf, copy your cert.pem and key.pem files to /opt/mailcow-dockerized/data/assets/ssl/, set the correct permissions (600 on the key, 644 on the cert), and restart the stack.
Step 9: Security Hardening
Before sending production email, lock down the environment:
- Firewall: Only allow ports that Mailcow requires:
- 25 (SMTP routing)
- 80 / 443 (HTTP/HTTPS for Web UI, ACME, ActiveSync)
- 143 / 993 (IMAP / IMAP over TLS)
- 110 / 995 (POP3 / POP3 over TLS — optional, only if you support legacy clients)
- 465 / 587 (SMTPS / Submission)
- 4190 (Sieve filtering)
- Rate Limiting: Go to the admin panel and configure per-mailbox rate limits. This prevents a compromised user account from blasting out thousands of spam emails and destroying your IP reputation.
- MTA-STS (Optional but Recommended): Modern providers like Google encourage MTA-STS. Mailcow can host the required policy file, but it takes two pieces to work: an _mta-sts TXT record (
v=STSv1; id=<unique-id>) and an mta-sts subdomain (e.g.,mta-sts.yourdomain.com) pointed at your server and served over valid HTTPS, since that's where senders fetch the actual policy file from. Publishing only the TXT record without the working HTTPS endpoint leaves MTA-STS non-functional. - Updates: Run ./update.sh regularly.
Step 10: Test Deliverability
Before putting your server into active use, verify your authentication:
- Port25 Verifier: Send a blank test email from your newly created mailbox to [email protected]. You will receive an automated reply analyzing your SPF, DKIM, iprev (Reverse DNS), and a SpamAssassin score. You want "pass" across the board.
- Mail-Tester: Go to mail-tester.com, send an email to the unique address provided, and aim for a 10/10 score.
- Real-World Test: Send emails to a Gmail account and an Outlook/Microsoft 365 account you control to ensure they land in the inbox.
Step 11: Warm Up the IP
If your IP address has no sending history, major providers will treat it suspiciously. Ramp up your email volume gradually:
- Week 1: Keep it under 50 messages/day to establish clean authentication.
- Weeks 2–3: Scale up to 200–500 messages/day. Monitor your test inboxes for any spam folder placements.
- Week 4+: Gradually scale toward your normal target volume.
Ongoing Maintenance
- Monitor your server's IP periodically via Spamhaus, Talos Intelligence, and SenderScore.
- Monitor your DMARC reports (sent to the email address in your rua= tag) for unauthorized sending attempts or authentication breaks.
- Regularly back up your Mailcow Docker volumes, as this is where all the mail database data lives. Mailcow provides a /helper-scripts/backup_and_restore.sh script for this purpose.
Summary
Mailcow gets you a fully self-hosted, production-capable mail stack in a single Docker Compose deployment: Postfix and Dovecot for mail transport and storage, Rspamd and ClamAV for filtering, SOGo for webmail, and a web admin UI tying it together. The install itself takes under an hour.
What actually determines whether your mail reaches the inbox is everything downstream of that: a clean IP, correct PTR, properly published SPF/DKIM/DMARC, TLS, sane rate limiting, and a gradual sending ramp. Do those consistently and you'll get deliverability on par with, or better than, most commercial providers — just not a guaranteed 100%, because that number isn't fully within any sender's control.
Need a Reliable Server for Your Mail Transport?
Self-hosting email requires a provider that offers clean IPs, full reverse DNS control, and doesn't arbitrarily block port 25. Stop fighting with restrictive virtual servers and move your communication stack to reliable bare metal.
Explore Fit Servers for high-performance, cost-effective dedicated servers perfectly tailored for Docker-based mail deployments. Take control of your data privacy and deliverability today.
View Dedicated Servers