> ## Content Index
> Fetch the complete content index at: https://sudosecurity.org/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to Self-Host Your Own Email Server With Mailcow in 2026 — Complete Setup Guide
- URL: https://sudosecurity.org/self-hosted-email-server-mailcow-setup-guide-2026/
- Published: 2026-04-29T04:10:00.000Z
- Updated: 2026-07-17T10:33:20.000Z
- Description: How to Self-Host Your Own Email Server With Mailcow in 2026 — Complete Setup Guide Meta Description: Stop letting Google and Microsoft read your email. This guide sets up a complete private email server with Mailcow on a NetCup VPS — DNS, SPF, DKIM, DMARC, TLS, webmail, and mobile clients.
- Author: Traven
- Tags: Self Hosting, Privacy, Linux, Cloud Hosting, Open Source, Systems Administration

Gmail knows what bank you use. It knows your doctor's name, your insurance provider, your salary from the job offer you accepted in 2019, and the flight you took to your mother's funeral. You didn't give Google that information — you gave it to the people who emailed you. Google read those emails anyway.

This isn't paranoia. It's the documented product. Gmail scans every message to power Smart Reply, Nudge, category tabs, and the ad targeting that follows you around the web. Microsoft does the same with Outlook. Both companies store your emails on servers in jurisdictions where governments can compel disclosure without your knowledge. Both companies have had their systems compromised in incidents affecting millions of users. Microsoft's 2023 Exchange breach, attributed to Chinese state actors, gave attackers access to email accounts for US government officials. The emails were stored on Microsoft's infrastructure. Microsoft's customers had no control over what happened next.

Running your own email server puts you back in control. Your emails live on hardware you pay for, in a jurisdiction you choose, accessible only with credentials you hold. Nobody reads them without getting through you first.

This guide sets up a complete, production-ready email server using [Mailcow](https://mailcow.email/?ref=sudosecurity.org) on a [NetCup](https://netcup.eu/?ref=sudosecurity.org) VPS — the setup we run at CoderOasis. By the end, you'll have a server handling multiple domains, a webmail interface at your own URL, mobile client setup on iOS and Android, proper spam filtering, and every email authentication standard configured to reach inboxes instead of spam folders.

## Why Is Mailcow the Best Self-Hosted Email Solution?

Running a raw Postfix/Dovecot stack is a week-long job. You configure each service individually, wire them together manually, handle TLS certificates yourself, build an admin interface from scratch, and debug cryptic MTA log formats when something breaks. Most people who try it give up before they send their first email.

Mailcow solves this by packaging everything in Docker containers that work together out of the box:

- **Postfix** — SMTP server for sending and receiving
- **Dovecot** — IMAP/POP3 for client connections
- **SOGo** — webmail interface with calendar and contacts
- **Rspamd** — spam filtering with machine learning
- **ClamAV** — antivirus scanning of attachments
- **Unbound** — local DNS resolver
- **Nginx** — web server and reverse proxy
- **acme-mailcow** — automatic Let's Encrypt certificate management  
One `docker compose up -d` starts all of them. Updates are a single script. The admin panel at `https://mail.yourdomain.com` handles everything: adding domains, creating mailboxes, configuring DKIM, reading Rspamd scores, blocking senders.

Alternatives exist. iRedMail is older and requires more manual configuration. Mailu is lighter but less featureful. Postal is built for high-volume sending. For a personal or small-team mail server with a usable admin interface, Mailcow has no real competition.

## What Server Do You Need to Run Mailcow?

### Why Does NetCup Work Well for Self-Hosted Email?

Mailcow's official documentation lists minimum requirements: 2 vCores, 2GB RAM, 20GB disk. The practical minimums for a server you'll actually rely on daily are higher.

We recommend NetCup because they meet the requirements that specifically matter for email hosting:

**Port 25 is open by default.** Most consumer cloud providers (AWS EC2, DigitalOcean) block port 25 on new instances to prevent spam abuse. Getting it unblocked requires a support ticket and explanation. NetCup's VPS plans come with port 25 open. Email hosting is a listed use case in their terms of service.

**Hetzner is the price/performance alternative** if NetCup is sold out in your preferred region. Their CX21 (2 vCores, 4GB RAM, 40GB SSD) at €3.29/month also has port 25 available on request. File a support ticket before configuring Mailcow.

**The specific NetCup plan we use:** NetCup VPS RS 2000 G10s — 4 vCores, 4GB RAM, 80GB NVMe SSD, 2.5Gbps uplink. Around €4-6/month depending on contract length. It handles Mailcow for multiple domains at CoderOasis without breaking a sweat.

Avoid shared hosting for this. Email servers need consistent port access and the ability to set custom PTR records. Shared hosting doesn't give you either.

### What Operating System Should You Use for Mailcow?

**Debian 12 (Bookworm)** is the best choice. Mailcow's team tests against it directly. It's stable, has a long support lifecycle, and Docker's official packages work cleanly on it. Ubuntu 24.04 LTS is a solid second option.

Do not use Ubuntu 22.10, 23.04, 23.10, or any non-LTS Ubuntu release. Mailcow specifically warns against these due to nftables and systemd-resolved conflicts that break container networking.

## How Do You Prepare the Server Before Installing Mailcow?

### How Do You Configure the Server Hostname?

Mailcow needs the server's Fully Qualified Domain Name (FQDN) set correctly before installation. The FQDN must match what you'll use for the `A` record pointing to this server — conventionally `mail.yourdomain.com`.

```bash
# Set the hostname (run as root)
hostnamectl set-hostname mail.yourdomain.com
 
# Verify
hostname -f
# Should output: mail.yourdomain.com

```

### Which Ports Does Mailcow Require?

Mailcow uses these ports. Verify nothing else is listening on them before installation:

```bash
# Check for port conflicts
ss -tulpn | grep -E ':25|:80|:110|:143|:443|:465|:587|:993|:995|:4190'

```

If anything appears, stop and disable the conflicting service:

```bash
# Common conflicts
systemctl stop apache2 nginx postfix exim4 2>/dev/null
systemctl disable apache2 nginx postfix exim4 2>/dev/null

```

Mailcow's nginx handles ports 80 and 443\. Mailcow's Postfix handles port 25\. If you have an existing web server or mail server running, it will conflict.

| Port | Service | Purpose                                 |
| ---- | ------- | --------------------------------------- |
| 25   | Postfix | Receiving email from other mail servers |
| 80   | Nginx   | HTTP → HTTPS redirect + ACME challenge  |
| 110  | Dovecot | POP3 (legacy, can disable)              |
| 143  | Dovecot | IMAP                                    |
| 443  | Nginx   | Admin panel, webmail, autodiscover      |
| 465  | Postfix | SMTP submission (legacy TLS)            |
| 587  | Postfix | SMTP submission (STARTTLS)              |
| 993  | Dovecot | IMAPS                                   |
| 995  | Dovecot | POP3S                                   |
| 4190 | Dovecot | Sieve (server-side mail filtering)      |

### How Do You Harden SSH Before Exposing the Server?

Before this server handles email for real addresses, lock down SSH access. Default password authentication on a public IP gets brute-forced within hours.

```bash
# Generate an SSH key on your local machine if you don't have one
ssh-keygen -t ed25519 -C "mailcow-server"
 
# Copy your public key to the server
ssh-copy-id root@your-server-ip
 
# Verify key-based login works, then disable password authentication
nano /etc/ssh/sshd_config

```

Change these settings in `sshd_config`:

```
PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
Port 22  # Consider changing to a non-standard port

```

```bash
systemctl restart sshd

```

Verify your key-based login works in a second terminal before closing your current session. Locking yourself out of a remote server is not a fun afternoon.

## How Do You Configure DNS Records for Mailcow?

DNS is where most Mailcow installations fail. Configure all seven records correctly before installing the software. Email authentication depends on DNS, and DNS propagates slowly — get it right first.

### What Is the A Record for a Mail Server?

The A record maps your mail subdomain to your server's IP address. Log into your domain registrar's DNS panel and add:

```
Type:  A
Name:  mail
Value: YOUR.SERVER.IP.ADDRESS
TTL:   3600

```

This makes `mail.yourdomain.com` resolve to your server. Every other record either points to this or depends on it.

### What Is an MX Record and Why Does Email Need One?

The MX (Mail Exchanger) record tells other mail servers where to deliver email addressed to your domain. Without it, nobody can send you email from external servers.

```
Type:     MX
Name:     @ (root domain)
Priority: 10
Value:    mail.yourdomain.com
TTL:      3600

```

### What Is an SPF Record and How Do You Set It Up?

SPF (Sender Policy Framework) is a TXT record that lists which servers are authorized to send email from your domain. Receiving servers check SPF to verify that mail claiming to be from your domain actually came from one of your listed servers.

```
Type:  TXT
Name:  @ (root domain)
Value: v=spf1 mx ~all
TTL:   3600

```

`v=spf1` declares this as an SPF record. `mx` authorizes the server in your MX record. `~all` is a soft fail — email from unlisted servers gets a warning, not an outright rejection. Use `-all` (hard fail) once you've verified everything is working correctly.

### What Is DKIM and How Does Mailcow Configure It?

DKIM (DomainKeys Identified Mail) adds a cryptographic signature to every outgoing email. The receiving server uses your public key (published in DNS) to verify that the message actually came from your server and wasn't modified in transit.

You cannot set the DKIM TXT record before installing Mailcow, because Mailcow generates the DKIM key pair. Add a placeholder for now and come back after installation:

```
Type:  TXT
Name:  dkim._domainkey
Value: (add after Mailcow installation)
TTL:   3600

```

After installation, navigate to **Configuration → Mail Setup → Domains → your domain → DKIM Keys** in the Mailcow admin panel. Copy the generated value and update this DNS record.

### What Is DMARC and How Do You Configure It?

DMARC (Domain-based Message Authentication, Reporting, and Conformance) builds on SPF and DKIM. It tells receiving servers what to do when either check fails: do nothing, quarantine, or reject. It also requests reports on authentication results sent to an email address you specify.

Start with `p=none` to monitor without affecting delivery:

```
Type:  TXT
Name:  _dmarc
Value: v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com; fo=1
TTL:   3600

```

`p=none` means take no action on failures — just report. After 1-2 weeks of monitoring your DMARC reports and confirming SPF and DKIM are passing for all legitimate outbound email, change to `p=quarantine` then eventually `p=reject`. Moving too fast to `p=reject` before verifying your authentication setup breaks mail delivery from legitimate sources.

### What Is a PTR Record and Why Is It Critical for Email?

The PTR record (Pointer record, or Reverse DNS) is the reverse of an A record. Where an A record maps a hostname to an IP, a PTR record maps an IP back to a hostname. For email, it maps your server's IP to `mail.yourdomain.com`.

Many mail servers reject email from IPs without a matching PTR record. It's the single most commonly missed DNS configuration, and missing it causes immediate rejection by ISPs.

Unlike every other DNS record, the PTR record is set at your server provider, not your domain registrar. In NetCup's Customer Control Panel (CCP):

1. Go to **Server** → your VPS → **Network**
2. Find your IPv4 address
3. Set **Reverse DNS** to `mail.yourdomain.com`
4. Repeat for your IPv6 address if enabled  
Do the same for IPv6\. Many modern mail servers check IPv6 PTR records.

```bash
# Verify the PTR record after setting it (allow up to 24 hours to propagate)
dig -x YOUR.SERVER.IP.ADDRESS +short
# Should return: mail.yourdomain.com.

```

### What Are Autodiscover and Autoconfig Records?

These CNAME records let email clients (Outlook, Thunderbird, Apple Mail) automatically configure themselves when a user adds your email address:

```
Type:  CNAME
Name:  autodiscover
Value: mail.yourdomain.com
TTL:   3600
 
Type:  CNAME
Name:  autoconfig
Value: mail.yourdomain.com
TTL:   3600

```

Not required for mail to work, but prevents users from manually entering IMAP/SMTP settings.

## How Do You Install Mailcow on Your Server?

### Installing Docker on Debian 12

Mailcow requires Docker Engine 24.0.0+ installed from Docker's official repository, not the version in Debian's default packages:

```bash
# Remove any old Docker packages
apt remove docker docker-engine docker.io containerd runc 2>/dev/null
 
# Install dependencies
apt update && apt install -y ca-certificates curl gnupg
 
# Add Docker's GPG key
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | \
  gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
 
# Add Docker's repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null
 
# Install Docker
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
 
# Verify
docker --version
# Docker version 26.x.x or newer
 
docker compose version
# Docker Compose version v2.x.x

```

### How Do You Clone and Configure Mailcow?

```bash
# Clone Mailcow into /opt/mailcow
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
 
# Generate the configuration file
./generate_config.sh

```

The script asks three questions:

1. **Mail server hostname (FQDN):** Enter `mail.yourdomain.com`
2. **Timezone:** Press Enter to use the server default, or enter your timezone (e.g., `Europe/Berlin`)
3. **Branch:** Enter `1` for master (stable)  
This generates `mailcow.conf`. Review it before starting:

```bash
cat mailcow.conf

```

Key settings to verify or adjust:

```bash
# mailcow.conf — important settings
 
MAILCOW_HOSTNAME=mail.yourdomain.com  # Should match what you entered
HTTP_PORT=80                           # Keep default unless port conflict
HTTPS_PORT=443                         # Keep default
SMTP_PORT=25                           # Keep default
SMTPS_PORT=465                         # Keep default
SUBMISSION_PORT=587                    # Keep default
 
# If you have another service on port 80/443, change these:
# HTTP_PORT=8080
# HTTPS_PORT=8443
 
# Skip ClamAV if RAM is tight (saves ~1GB RAM)
# Set SKIP_CLAMD=y to disable antivirus
SKIP_CLAMD=n

```

If your server has only 2GB RAM and ClamAV is pushing it, set `SKIP_CLAMD=y`. Rspamd will still catch most spam through heuristics and reputation checks. ClamAV specifically targets malicious attachments.

### How Do You Start Mailcow for the First Time?

```bash
# Pull all Docker images (takes 5-15 minutes on first run)
docker compose pull
 
# Start Mailcow in the background
docker compose up -d
 
# Watch the startup logs — watch for the Let's Encrypt certificate request
docker compose logs -f acme-mailcow

```

The `acme-mailcow` container requests a Let's Encrypt TLS certificate for `mail.yourdomain.com`. This requires:

- Port 80 to be open from the internet (no firewall blocking it)
- The A record for `mail.yourdomain.com` to already be propagated  
If certificate provisioning fails, check:

```bash
# Check ACME logs for the specific error
docker compose logs acme-mailcow | tail -50
 
# Verify DNS is propagated
dig mail.yourdomain.com A +short
# Must return your server's IP

```

When Mailcow is running, all 15+ containers should show as running:

```bash
docker compose ps

```

Every service should show `Up` or `Up (healthy)`. If any show `Restarting`, check their logs:

```bash
docker compose logs [service-name] --tail=100

```

## How Do You Configure Mailcow After Installation?

### How Do You Log Into the Admin Panel?

Navigate to `https://mail.yourdomain.com` in your browser. The default admin credentials are:

```
Username: admin
Password: moohoo

```

**Change this password immediately.** Go to **Access** → **Edit administrator details** → update the password to something 20+ characters.

### How Do You Add Your Domain to Mailcow?

Go to **Configuration → Mail Setup → Domains → Add domain.**

- **Domain:** `yourdomain.com` (without the mail subdomain)
- **Description:** anything recognizable
- **Quota:** default is 10GB per domain
- **Mailbox quota:** default is 3GB per mailbox — adjust to match your disk space  
Click **Add.** Mailcow generates a DKIM key pair for the domain automatically.

### How Do You Get the DKIM Key to Add to DNS?

After adding the domain, click the **DNS** button next to it. Mailcow shows a complete list of required DNS records with green/red indicators showing which are currently configured correctly.

The DKIM record looks like:

```
Name:  dkim._domainkey.yourdomain.com
Type:  TXT
Value: v=DKIM1; k=rsa; t=s; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...

```

Copy the entire `p=...` value and add it to your DNS. Some DNS providers have a 255-character TXT string limit. DKIM keys exceed this. Most providers handle this automatically by splitting into multiple strings. If yours doesn't, split the `p=` value yourself into two quoted strings:

```
"v=DKIM1; k=rsa; t=s; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ..." "8AMIIBCgKCAQEA..."

```

After adding the DKIM record, wait for DNS propagation (anywhere from 5 minutes to 24 hours), then verify the green checkmarks in Mailcow's DNS panel.

### How Do You Create a Mailbox?

**Configuration → Mail Setup → Mailboxes → Add mailbox.**

- **Username:** the part before the @ (e.g., `traven` for `traven@yourdomain.com`)
- **Domain:** select from dropdown
- **Full name:** display name in email clients
- **Password:** use a password manager to generate 20+ characters
- **Quota:** 0 uses the domain default  
Click **Add.** Your mailbox is ready.

## How Do You Test Email Deliverability?

Before using this for real communication, verify your configuration actually reaches inboxes.

### How Do You Use mail-tester.com?

Navigate to [mail-tester.com](https://www.mail-tester.com/?ref=sudosecurity.org). It gives you a unique email address. Send a real email to it from your new mailbox (through SOGo webmail at `https://mail.yourdomain.com/SOGo/`). Wait 30 seconds, click **Check your score.**

Target: **9/10 or higher.** A perfect 10 means every authentication layer is correct and your IP has no reputation problems.

Common reasons for losing points:

- **SPF fails:** Check your SPF TXT record is set correctly
- **DKIM fails:** Verify the DKIM TXT record matches what Mailcow shows exactly
- **PTR mismatch:** Verify your reverse DNS at NetCup points to `mail.yourdomain.com`
- **Blacklisted IP:** New VPS IPs occasionally appear on blocklists from previous tenants

### How Do You Check if Your IP Is Blacklisted?

```bash
# Check MXToolbox for common blacklists
curl -s "https://mxtoolbox.com/SuperTool.aspx?action=blacklist&run=toolpage&input=YOUR.SERVER.IP"
 
# Or use the command line check
dig +short YOUR.REVERSED.IP.in-addr.arpa.zen.spamhaus.org
# No answer = not blacklisted
# 127.0.0.2 = listed on Spamhaus ZEN

```

If your IP is blacklisted, check the specific blocklist's removal process. Most accept removal requests with a brief explanation. Spamhaus's removal form at `https://www.spamhaus.org/lookup/` is the most common.

### How Do You Verify All Authentication Records Are Working?

```bash
# Check all DNS records from your server
dig yourdomain.com MX +short
dig yourdomain.com TXT +short | grep spf
dig dkim._domainkey.yourdomain.com TXT +short
dig _dmarc.yourdomain.com TXT +short
dig -x YOUR.SERVER.IP +short  # PTR check
 
# Send an authentication check email (runs SPF, DKIM, DMARC checks and replies with results)
# From your new mailbox, send any email to:
# check-auth@verifier.port25.com
# You'll receive a full report within minutes

```

The Port25 verifier reply confirms every authentication layer independently. You want to see `SPF check: pass`, `DKIM check: pass`, and `SpamAssassin check: ham`.

## How Do You Connect Email Clients to Your Mailcow Server?

### What Are the Connection Settings for Mailcow?

These settings work for any email client — Thunderbird, Apple Mail, Outlook, Spark, Fastmail-compatible clients:

| Setting                | Value                                   |
| ---------------------- | --------------------------------------- |
| Incoming Server (IMAP) | mail.yourdomain.com                     |
| IMAP Port              | 993                                     |
| IMAP Security          | SSL/TLS                                 |
| Outgoing Server (SMTP) | mail.yourdomain.com                     |
| SMTP Port              | 587                                     |
| SMTP Security          | STARTTLS                                |
| Username               | Full email address (you@yourdomain.com) |
| Password               | Your mailbox password                   |

### How Do You Set Up Mailcow on iPhone (iOS)?

1. Settings → Mail → Accounts → Add Account → Other → Add Mail Account
2. Enter your name, email address, and password
3. iOS will attempt autodiscover — if you added the autodiscover CNAME record, it auto-fills settings
4. If auto-configure fails: tap **IMAP**, enter the settings from the table above manually
5. Enable Mail and Contacts, tap Save

### How Do You Set Up Mailcow on Android?

1. Open your email app (Gmail app works with IMAP, or use FairEmail for a privacy-respecting option)
2. Add account → Other
3. Enter your email address → Manual setup → IMAP
4. Incoming: `mail.yourdomain.com`, port 993, SSL/TLS
5. Outgoing: `mail.yourdomain.com`, port 587, STARTTLS
6. Enter your mailbox password for both  
**FairEmail** is worth highlighting specifically. It's open source, has no trackers, doesn't sync your contacts to a third-party server, and costs a one-time €1 for the full version. It's the email client that matches the privacy philosophy of running your own server.

### How Do You Access Mailcow Webmail?

Navigate to `https://mail.yourdomain.com/SOGo/`. Log in with your full email address and password. SOGo provides a full web-based email, calendar, and contacts interface — comparable to Gmail's web UI but running on your server.

## How Do You Secure and Maintain a Mailcow Server?

### How Do You Enable Automatic Updates?

Mailcow provides an update script that handles pulling new Docker images, applying migrations, and restarting services:

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

```

Automate this with a cron job. Run it weekly during off-peak hours:

```bash
crontab -e
 
# Add this line — runs every Sunday at 3AM, logs to /var/log/mailcow-update.log
0 3 * * 0 cd /opt/mailcow-dockerized && ./update.sh --force >> /var/log/mailcow-update.log 2>&1

```

Keep the OS updated separately:

```bash
# Automatic unattended security upgrades
dpkg-reconfigure -plow unattended-upgrades

```

### How Do You Back Up Mailcow?

Mailcow's data lives in Docker volumes under `/var/lib/docker/volumes/`. The email store, configuration, and database are all there.

```bash
#!/bin/bash
# /usr/local/bin/mailcow-backup.sh
# Run nightly — backs up all Mailcow volumes to /backups/mailcow
 
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR=/backups/mailcow
MAILCOW_DIR=/opt/mailcow-dockerized
 
mkdir -p $BACKUP_DIR
 
# Stop Mailcow for a consistent backup (brief downtime)
cd $MAILCOW_DIR
docker compose down
 
# Backup all named volumes
for volume in $(docker volume ls -q | grep mailcow); do
  docker run --rm \
    -v $volume:/data:ro \
    -v $BACKUP_DIR:/backup \
    alpine tar czf /backup/${volume}_${DATE}.tar.gz /data
done
 
# Backup mailcow.conf
cp $MAILCOW_DIR/mailcow.conf $BACKUP_DIR/mailcow.conf_${DATE}
 
# Restart Mailcow
docker compose up -d
 
# Remove backups older than 14 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +14 -delete
 
echo "Backup complete: $DATE"

```

```bash
chmod +x /usr/local/bin/mailcow-backup.sh
# Run nightly at 2AM
echo "0 2 * * * /usr/local/bin/mailcow-backup.sh >> /var/log/mailcow-backup.log 2>&1" | crontab -

```

An alternative: Mailcow has a built-in helper at `helper-scripts/backup_and_restore.sh` that handles backup and restoration of individual components with less downtime.

### How Do You Harden Mailcow Against Brute Force Attacks?

Mailcow includes Fail2Ban integration by default. It watches authentication logs and blocks IPs after failed login attempts. Verify it's running:

```bash
docker compose ps fail2ban-mailcow
# Should show: Up

```

Configure the ban duration in `data/conf/fail2ban/jail.local`:

```
[DEFAULT]
bantime = 86400   # 24 hours
findtime = 600    # 10 minute window
maxretry = 5      # 5 failures triggers ban

```

Restart the Fail2Ban container after changes:

```bash
docker compose restart fail2ban-mailcow

```

For SSH brute force (separate from Mailcow), install `fail2ban` at the OS level:

```bash
apt install fail2ban
systemctl enable fail2ban --now

```

### How Do You Monitor Mailcow's Health?

```bash
# Check all containers are running
docker compose -f /opt/mailcow-dockerized/docker-compose.yml ps
 
# Check for queued mail (should be empty during normal operation)
docker compose exec postfix-mailcow postqueue -p
 
# Flush stuck queue
docker compose exec postfix-mailcow postqueue -f
 
# Check Rspamd's spam filter statistics
docker compose exec rspamd-mailcow rspamc stat
 
# View live SMTP log
docker compose logs -f postfix-mailcow
 
# Check recent delivery status (sent, deferred, bounced)
docker compose logs postfix-mailcow | grep "status=" | tail -50

```

A healthy server has an empty or near-empty mail queue. Mail that's been deferred means the receiving server temporarily rejected it — Postfix retries automatically. Bounced mail (permanent failure) means the destination address doesn't exist or their server permanently rejected it.

## How Do You Advance Your DMARC Policy to Reject?

After running with `p=none` for two weeks and reviewing your DMARC reports, advance the policy in stages:

```bash
# Week 1-2: p=none (monitoring only)
"v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; fo=1"
 
# Week 3-4: p=quarantine (failed auth goes to spam)
"v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; fo=1; pct=25"
# pct=25 applies the policy to only 25% of failing messages initially
 
# Week 5+: p=reject (failed auth is rejected outright)
"v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; fo=1"

```

The `pct` parameter is a safety valve during the quarantine phase. Setting it to 25 means only a quarter of SPF/DKIM failures get quarantined. If something breaks and you're still sending legitimate mail that fails authentication, only 25% of it gets flagged while you diagnose the problem. Scale it up to 100 over a week once you're confident.

A DMARC policy of `p=reject` means any email claiming to be from your domain that fails authentication gets rejected at the receiving server. Nobody can spoof your domain and have the email delivered.

## What About IP Warmup — Why Does It Matter?

A new server IP address has no email sending reputation. Major providers — Gmail, Outlook, Yahoo — judge incoming mail partly by the IP's history. An IP that suddenly starts sending hundreds of emails a day from a standing start looks like a spam operation.

The warmup process builds reputation gradually:

**Week 1:** Send 20-50 emails per day. Real conversations with real recipients. Focus on getting replies, because replies are the strongest positive reputation signal.

**Week 2:** Scale to 100-200 per day.

**Week 3-4:** 500 per day.

**Month 2+:** Scale to your actual sending needs.

This matters most if you're using this server for any bulk sending — newsletters, notifications, announcements. For personal email (a few dozen messages a day), you'll naturally stay within safe limits and reputation builds passively.

---

## Frequently Asked Questions About Self-Hosted Email With Mailcow

**Is self-hosted email harder to maintain than Gmail?**  
After initial setup (1-3 hours), monthly maintenance is 30-60 minutes: running `./update.sh` weekly, checking that certificates renewed, skimming mail logs for delivery problems. It's more work than zero, but not much more.

**Can I migrate my Gmail history to Mailcow?**  
Yes. imapsync copies all email between IMAP servers. Google Takeout exports your Gmail in Mbox format, which imapsync or Thunderbird's ImportExportTools can import into your IMAP server. The complete migration guide is longer than this article allows, but it's a solved problem.

**Will my self-hosted email get blocked by Gmail?**  
Not if properly configured. The combination of SPF, DKIM, DMARC, and a clean PTR record is what Gmail checks. A mail-tester.com score of 9/10 means you're delivering correctly. If Gmail specifically gives you trouble, their Postmaster Tools at `postmaster.google.com` show your domain and IP reputation directly.

**What happens if my VPS goes down?**  
Email from external servers gets deferred and retried for 5 days by default. If your server is back up within that window, you receive everything. For high-availability setups, you can configure a backup MX record pointing to a second server. For personal email, the 5-day retry window covers most outages.

**Can I add multiple domains to Mailcow?**  
Yes. Mailcow supports unlimited domains. Each domain gets its own DKIM key, mailboxes, aliases, and spam filtering settings. Add more domains through **Configuration → Mail Setup → Domains** at any time.

---

*For the full self-hosted stack that this server fits into, the* [*self-hosted productivity guide*](https://sudosecurity.org/self-hosted-productivity-stack-nextcloud-vaultwarden-immich-jellyfin-paperless-2026/) *covers Nextcloud for file sync, Vaultwarden for passwords, Immich for photos, and Jellyfin for media — all running alongside Mailcow on the same or similar infrastructure. The* [*Docker overview*](https://sudosecurity.org/what-is-docker/) *covers the container fundamentals Mailcow runs on. The* [*cybersecurity overview*](https://sudosecurity.org/what-is-cybersecurity/) *covers the threat model you're managing when you expose services to the internet.*