Deploying Mailcow with Docker and Traefik for a Full E-Mail Stack
Table of Contents 📑
- Changelog
- 1. Prerequisites
- 2. Directory Structure
- 3. Clone the Mailcow Repository
- 4. Generate the Configuration File
- 5. Configure for Traefik Integration
- 6. Launch Mailcow
- 7. DNS Configuration
- 8. Firewall Configuration
- 9. Initial Mailcow Setup
- 11. Testing and Verification
- 12. Create Mailboxes and Log In
- Conclusion
Mailcow is a powerful and flexible open-source mail server suite that allows you to manage your email communications securely and efficiently. With Mailcow, you can create multiple email domains and accounts, manage users, and leverage features like spam filtering and encryption, giving you full control over your email infrastructure. This guide will show you how to set up Mailcow using Docker Compose behind an existing Traefik reverse proxy.
Changelog
Date | Change |
---|---|
2025-09-18 | Initial Version: First version of this guide was created. |
1. Prerequisites
This guide assumes you have a fully functional server environment with the following components already set up:
- Traefik v3 and CrowdSec with Docker Compose: This is the foundation for our reverse proxy, security, and certificate management.
- Docker and Docker Compose: Must be installed on your server.
- Required Tools: You will need
git
andjq
. Install them with:sudo apt update && sudo apt install -y git jq
sudo
or root access.
2. Directory Structure
First, create a dedicated directory for your Mailcow installation.
sudo mkdir -p /opt/containers/mailcow
3. Clone the Mailcow Repository
Clone the latest version of the Mailcow Dockerized project from GitHub into the directory you just created.
sudo git clone https://github.com/mailcow/mailcow-dockerized /opt/containers/mailcow
4. Generate the Configuration File
Navigate into the new directory and run the configuration generation script.
cd /opt/containers/mailcow
./generate_config.sh
You will be prompted for the following information:
- Mail server hostname (FQDN): Enter the fully qualified domain name for your mail server, for example,
mail.your-domain.com
. - Timezone: Press Enter to accept the default or provide your own.
- Available Branches: Press
1
to select the master branch.
5. Configure for Traefik Integration
To make Mailcow work with our external Traefik instance, we need to create an override file and modify the main configuration.
5.1. Create docker-compose.override.yml
This file contains all our customizations, telling Mailcow to use the external proxy
network and defining labels for Traefik to route traffic correctly. It also sets up a certdumper
service, which is crucial for sharing Traefik’s Let’s Encrypt certificates with Mailcow’s services (Postfix and Dovecot).
Create the file:
sudo tee docker-compose.override.yml > /dev/null << 'EOF'
networks:
proxy:
name: proxy
external: true
services:
certdumper:
image: ghcr.io/kereis/traefik-certs-dumper:latest
restart: unless-stopped
network_mode: none
command: --restart-containers mailcowdockerized-postfix-mailcow-1,mailcowdockerized-dovecot-mailcow-1
volumes:
- /opt/containers/traefik-stack/traefik/certs:/traefik:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/assets/ssl:/output:rw
environment:
DOMAIN: ${MAILCOW_HOSTNAME}
ACME_FILE_PATH: "/traefik/acme.json"
healthcheck:
test: ["CMD", "/usr/bin/healthcheck"]
interval: 30s
timeout: 10s
retries: 5
nginx-mailcow:
ports: !reset
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
# HTTP Router (for ACME challenge and redirect)
- "traefik.http.routers.nginx-mailcow.entrypoints=web"
- "traefik.http.routers.nginx-mailcow.rule=Host(`mail.your-domain.com`, `autodiscover.your-domain.com`, `autoconfig.your-domain.com`, `mta-sts.your-domain.com`)"
# Middleware for redirect
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.nginx-mailcow.middlewares=redirect-to-https@docker"
# HTTPS Router
- "traefik.http.routers.nginx-mailcow-secure.entrypoints=websecure"
- "traefik.http.routers.nginx-mailcow-secure.rule=Host(`mail.your-domain.com`, `autodiscover.your-domain.com`, `autoconfig.your-domain.com`, `mta-sts.your-domain.com`)"
- "traefik.http.routers.nginx-mailcow-secure.tls=true"
- "traefik.http.routers.nginx-mailcow-secure.tls.certresolver=tls_resolver"
- "traefik.http.routers.nginx-mailcow-secure.service=nginx-mailcow"
- "traefik.http.routers.nginx-mailcow-secure.middlewares=security-headers@file,crowdsec-bouncer@docker"
# Service Definition
- "traefik.http.services.nginx-mailcow.loadbalancer.server.port=8080"
EOF
⚠️ IMPORTANT |
You must replace
|
5.2. Adjust mailcow.conf
Next, edit the main configuration file to integrate with Traefik and prevent conflicts.
sudo nano /opt/containers/mailcow/mailcow.conf
Make the following critical changes:
Change Internal Ports: Prevent conflicts with Traefik’s ports 80 and 443. This tells Mailcow’s internal Nginx to listen on different ports, which Traefik will then route to.
HTTP_PORT=8080 HTTPS_PORT=8443
Disable Mailcow’s Let’s Encrypt: Traefik is responsible for all certificate management.
SKIP_LETS_ENCRYPT=y
Add SAN for Internal TLS: This ensures Mailcow’s internal services trust the Traefik-provided certificate for the mail server hostname.
ADDITIONAL_SAN=${MAILCOW_HOSTNAME}
5.3. Activate MTA-STS
MTA-STS (Mail Transfer Agent-Strict Transport Security) is a security standard that helps prevent man-in-the-middle attacks by ensuring emails are transmitted over secure TLS connections. We’ll create a policy file that Mailcow will serve.
First, create the required directory:
sudo mkdir -p /opt/containers/mailcow/data/web/.well-known/
Now, create the policy file. We will start with an enforce
policy for production use.
sudo tee /opt/containers/mailcow/data/web/.well-known/mta-sts.txt > /dev/null << 'EOF'
version: STSv1
mode: enforce
max_age: 15552000
mx: mail.your-domain.com
EOF
⚠️ IMPORTANT |
You must replace
|
6. Launch Mailcow
You can now start the Mailcow stack.
cd /opt/containers/mailcow
docker compose up -d
💡 TROUBLESHOOTING: POOL OVERLAPS |
If you encounter an error like |
7. DNS Configuration
Correct DNS setup is critical for a mail server to function.
7.1. Reverse DNS (PTR Record)
Your server’s Reverse DNS (PTR) record must match the hostname you configured in mailcow.conf
(mail.your-domain.com
). This is usually set in your server provider’s control panel and is essential for not being marked as spam.
7.2. DNS Records
In your domain’s DNS management panel, add the following records. We start with a non-restrictive DMARC policy (p=none
) to prevent legitimate emails from being rejected during the initial setup. You can switch to p=quarantine
or p=reject
later once you have confirmed that all your email sources are correctly configured.
Name | Type | Value |
---|---|---|
A | your-server-ip | |
autodiscover | CNAME | mail.your-domain.com. |
autoconfig | CNAME | mail.your-domain.com. |
imap | CNAME | mail.your-domain.com. |
pop3 | CNAME | mail.your-domain.com. |
smtp | CNAME | mail.your-domain.com. |
@ | MX 0 | mail.your-domain.com. |
SPF | ||
@ | TXT | v=spf1 mx a -all |
DMARC | ||
_dmarc | TXT | v=DMARC1; p=none; rua=mailto:admin@your-domain.com |
MTA-STS | ||
mta-sts | CNAME | mail.your-domain.com. |
_mta-sts | TXT | v=STSv1; id=2025091401 |
_smtp._tls | TXT | v=TLSRPTv1; rua=mailto:admin@your-domain.com |
Service Records | ||
_autodiscover._tcp | SRV | 0 1 443 mail.your-domain.com. |
_caldavs._tcp | SRV | 0 1 443 mail.your-domain.com. |
_carddavs._tcp | SRV | 0 1 443 mail.your-domain.com. |
_imaps._tcp | SRV | 0 1 993 mail.your-domain.com. |
_pop3s._tcp | SRV | 0 1 995 mail.your-domain.com. |
_submission._tcp | SRV | 0 1 587 mail.your-domain.com. |
_smtps._tcp | SRV | 0 1 465 mail.your-domain.com. |
A DKIM record will be added later after it’s generated by Mailcow.
8. Firewall Configuration
Your firewall must allow traffic on several ports for email services to be reachable.
Port | Service | Protocol |
---|---|---|
25 | SMTP | TCP |
587 | Submission | TCP |
465 | SMTPS | TCP |
143 | IMAP | TCP |
993 | IMAPS | TCP |
110 | POP3 | TCP |
995 | POP3S | TCP |
4190 | ManageSieve | TCP |
Use ufw
to open these ports:
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 465/tcp
sudo ufw allow 143/tcp
sudo ufw allow 993/tcp
sudo ufw allow 110/tcp
sudo ufw allow 995/tcp
sudo ufw allow 4190/tcp
sudo ufw status
9. Initial Mailcow Setup
Navigate to your Mailcow UI at https://mail.your-domain.com
.
- Default Username:
admin
- Default Password:
moohoo
First, change the administrator password under System -> Configuration -> Edit.
10.1. Add Your Domain
Go to Email -> Configuration and click “Add domain”. Enter your main domain (e.g., your-domain.com
, not mail.your-domain.com
).
10.2. Generate DKIM Key
A DKIM key is essential for email authentication.
- Go to System -> Configuration.
- Navigate to the Options -> ARC/DKIM keys tab.
- A 2048-bit key should already be generated for your domain. Copy the public key text from the text box.
- Go back to your DNS provider and add a new TXT record:
- Name:
dkim._domainkey
- Value: Paste the entire copied key, including the
v=DKIM1;k=rsa;p=...
part.
- Name:
11. Testing and Verification
After waiting for DNS propagation, thoroughly test your setup.
11.1. Internal DNS and Certificate Check
- Mailcow DNS Check: In the Mailcow UI, go to Email -> Configuration -> DNS next to your domain for an internal check of your records.
- Verify Certificates: Ensure that the certificates from Traefik have been correctly passed to Mailcow’s services. Run these commands, replacing
mail.your-domain.com
with your mail server’s FQDN:
In the output, you should see a certificate chain issued by Let’s Encrypt. If you see a “self-signed certificate”, there is a problem with the# Check SMTP certificate echo "Q" | openssl s_client -starttls smtp -crlf -connect mail.your-domain.com:587 # Check IMAP certificate echo "Q" | openssl s_client -starttls imap -crlf -connect mail.your-domain.com:143
certdumper
service or theADDITIONAL_SAN
variable inmailcow.conf
. Check the certdumper logs:cd /opt/containers/mailcow docker compose logs certdumper
11.2. External Testing Tools
- mail-tester.com: Send an email to the address provided on their site to get a score out of 10.
- mxtoolbox.com: Provides various checks for your mail server.
- checktls.com/TestReceiver: Use this to specifically verify your MTA-STS configuration.
12. Create Mailboxes and Log In
Under Email -> Mailboxes, you can add new users. Once a user is created, you can access the webmail interface (SOGo) by clicking Apps -> Webmail in the main UI or by going directly to https://mail.your-domain.com/SOGo/
.
Conclusion
You have now successfully deployed a full-featured Mailcow e-mail server. By leveraging Docker for containerization and Traefik for reverse proxying and certificate management, you have a secure, robust, and maintainable mail solution. This setup provides you with complete control over your email, enhanced security through features like MTA-STS, and the flexibility to manage multiple domains and users with ease.