docker.recipes

Mailcow Complete Email Server

advanced

Full-featured email server with Dovecot, Postfix, SOGo webmail, and rspamd spam filtering.

Overview

Mailcow is a complete, dockerized mail server solution that combines the most robust open-source email components into a unified platform. Originally developed as an alternative to complex manual email server setups, mailcow integrates Postfix for SMTP services, Dovecot for IMAP/POP3, SOGo for webmail and groupware functionality, and rspamd for advanced spam filtering and reputation management. This creates a production-ready email infrastructure that rivals commercial solutions while maintaining full control over your data. The architecture leverages Postfix as the mail transfer agent handling incoming and outgoing messages, while Dovecot manages mailbox storage and client connections through IMAP and POP3 protocols. SOGo provides a modern web interface for email, calendar, and contacts with ActiveSync support for mobile devices. Rspamd performs real-time spam analysis using machine learning algorithms, DKIM signing, and reputation scoring, with Redis caching frequently accessed data and MySQL storing user accounts, configurations, and message metadata. This combination addresses the critical challenge of running enterprise-grade email infrastructure without the complexity of manually configuring and maintaining individual components. Small to medium businesses, privacy-conscious organizations, and system administrators benefit from mailcow's integrated approach, which provides advanced features like two-factor authentication, alias management, automatic backup capabilities, and comprehensive logging while eliminating the traditional pain points of email server administration.

Key Features

  • Rspamd advanced spam filtering with Bayes classification, neural networks, and real-time reputation scoring
  • SOGo ActiveSync protocol support for native mobile device integration with push notifications
  • Postfix multi-instance architecture with automatic DKIM key generation and DNS record management
  • Dovecot full-text search with Solr backend integration and server-side mail filtering via Sieve
  • Built-in quarantine management system with user self-service portal for reviewing blocked messages
  • Automatic Let's Encrypt certificate provisioning and renewal with DANE TLSA record support
  • Real-time monitoring dashboard with mail queue status, spam statistics, and system resource usage
  • Multi-domain support with per-domain policies, quotas, and administrator delegation

Common Use Cases

  • 1Small business email infrastructure replacing expensive hosted solutions like Microsoft 365
  • 2Privacy-focused organizations requiring full control over email data and encryption keys
  • 3Managed service providers offering white-label email hosting to multiple clients
  • 4Educational institutions needing cost-effective email with calendar and contact synchronization
  • 5Development teams requiring dedicated email services for application notifications and user communications
  • 6Remote work environments needing reliable email with mobile device management capabilities
  • 7Compliance-sensitive industries requiring email archiving, audit trails, and data residency control

Prerequisites

  • Minimum 4GB RAM and 20GB storage space for production deployment with multiple domains
  • Valid domain name with ability to configure MX, SPF, DKIM, and DMARC DNS records
  • Clean IP address reputation (not blacklisted) with reverse DNS properly configured
  • SSL certificate or ability to obtain Let's Encrypt certificates for mail.yourdomain.com
  • Open firewall ports 25, 80, 110, 143, 443, 465, 587, 993, 995 for full functionality
  • Basic understanding of email protocols (SMTP, IMAP, POP3) and DNS record management

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 unbound-mailcow:
3 image: mailcow/unbound:latest
4 volumes:
5 - ./data/hooks/unbound:/hooks:Z
6 - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
7 networks:
8 mailcow-network:
9 aliases:
10 - unbound
11
12 mysql-mailcow:
13 image: mariadb:10.11
14 command: --innodb-buffer-pool-size=256M
15 volumes:
16 - mysql-vol-1:/var/lib/mysql
17 - mysql-socket-vol-1:/var/run/mysqld
18 - ./data/conf/mysql/:/etc/mysql/conf.d/:ro,Z
19 environment:
20 MYSQL_ROOT_PASSWORD: ${DBROOT}
21 MYSQL_DATABASE: ${DBNAME}
22 MYSQL_USER: ${DBUSER}
23 MYSQL_PASSWORD: ${DBPASS}
24 networks:
25 - mailcow-network
26 restart: unless-stopped
27
28 redis-mailcow:
29 image: redis:alpine
30 volumes:
31 - redis-vol-1:/data
32 networks:
33 - mailcow-network
34 restart: unless-stopped
35
36 rspamd-mailcow:
37 image: mailcow/rspamd:latest
38 depends_on:
39 - redis-mailcow
40 volumes:
41 - ./data/conf/rspamd/custom/:/etc/rspamd/custom:Z
42 - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:Z
43 - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:Z
44 - rspamd-vol-1:/var/lib/rspamd
45 networks:
46 - mailcow-network
47 restart: unless-stopped
48
49 dovecot-mailcow:
50 image: mailcow/dovecot:latest
51 depends_on:
52 - mysql-mailcow
53 volumes:
54 - ./data/conf/dovecot:/etc/dovecot:Z
55 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
56 - vmail-vol-1:/var/vmail
57 environment:
58 DBNAME: ${DBNAME}
59 DBUSER: ${DBUSER}
60 DBPASS: ${DBPASS}
61 networks:
62 - mailcow-network
63 restart: unless-stopped
64
65 postfix-mailcow:
66 image: mailcow/postfix:latest
67 depends_on:
68 - mysql-mailcow
69 volumes:
70 - ./data/conf/postfix:/etc/postfix:Z
71 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
72 - postfix-vol-1:/var/spool/postfix
73 environment:
74 DBNAME: ${DBNAME}
75 DBUSER: ${DBUSER}
76 DBPASS: ${DBPASS}
77 ports:
78 - "25:25"
79 - "465:465"
80 - "587:587"
81 networks:
82 - mailcow-network
83 restart: unless-stopped
84
85 sogo-mailcow:
86 image: mailcow/sogo:latest
87 depends_on:
88 - mysql-mailcow
89 - redis-mailcow
90 environment:
91 DBNAME: ${DBNAME}
92 DBUSER: ${DBUSER}
93 DBPASS: ${DBPASS}
94 MAILCOW_HOSTNAME: ${MAILCOW_HOSTNAME}
95 networks:
96 - mailcow-network
97 restart: unless-stopped
98
99 nginx-mailcow:
100 image: nginx:alpine
101 depends_on:
102 - sogo-mailcow
103 - rspamd-mailcow
104 ports:
105 - "80:80"
106 - "443:443"
107 volumes:
108 - ./data/conf/nginx:/etc/nginx/conf.d:ro,Z
109 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
110 networks:
111 - mailcow-network
112 restart: unless-stopped
113
114volumes:
115 mysql-vol-1:
116 mysql-socket-vol-1:
117 redis-vol-1:
118 rspamd-vol-1:
119 vmail-vol-1:
120 postfix-vol-1:
121
122networks:
123 mailcow-network:
124 driver: bridge

.env Template

.env
1# Hostname
2MAILCOW_HOSTNAME=mail.example.com
3
4# Database
5DBNAME=mailcow
6DBUSER=mailcow
7DBPASS=secure_db_password
8DBROOT=secure_root_password
9
10# Timezone
11TZ=UTC

Usage Notes

  1. 1Access admin at https://mail.example.com/admin
  2. 2SOGo webmail at https://mail.example.com/SOGo
  3. 3Configure DNS records (MX, SPF, DKIM, DMARC)
  4. 4Use mailcow generate_config.sh for initial setup

Individual Services(8 services)

Copy individual services to mix and match with your existing compose files.

unbound-mailcow
unbound-mailcow:
  image: mailcow/unbound:latest
  volumes:
    - ./data/hooks/unbound:/hooks:Z
    - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
  networks:
    mailcow-network:
      aliases:
        - unbound
mysql-mailcow
mysql-mailcow:
  image: mariadb:10.11
  command: "--innodb-buffer-pool-size=256M"
  volumes:
    - mysql-vol-1:/var/lib/mysql
    - mysql-socket-vol-1:/var/run/mysqld
    - ./data/conf/mysql/:/etc/mysql/conf.d/:ro,Z
  environment:
    MYSQL_ROOT_PASSWORD: ${DBROOT}
    MYSQL_DATABASE: ${DBNAME}
    MYSQL_USER: ${DBUSER}
    MYSQL_PASSWORD: ${DBPASS}
  networks:
    - mailcow-network
  restart: unless-stopped
redis-mailcow
redis-mailcow:
  image: redis:alpine
  volumes:
    - redis-vol-1:/data
  networks:
    - mailcow-network
  restart: unless-stopped
rspamd-mailcow
rspamd-mailcow:
  image: mailcow/rspamd:latest
  depends_on:
    - redis-mailcow
  volumes:
    - ./data/conf/rspamd/custom/:/etc/rspamd/custom:Z
    - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:Z
    - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:Z
    - rspamd-vol-1:/var/lib/rspamd
  networks:
    - mailcow-network
  restart: unless-stopped
dovecot-mailcow
dovecot-mailcow:
  image: mailcow/dovecot:latest
  depends_on:
    - mysql-mailcow
  volumes:
    - ./data/conf/dovecot:/etc/dovecot:Z
    - ./data/assets/ssl:/etc/ssl/mail:ro,Z
    - vmail-vol-1:/var/vmail
  environment:
    DBNAME: ${DBNAME}
    DBUSER: ${DBUSER}
    DBPASS: ${DBPASS}
  networks:
    - mailcow-network
  restart: unless-stopped
postfix-mailcow
postfix-mailcow:
  image: mailcow/postfix:latest
  depends_on:
    - mysql-mailcow
  volumes:
    - ./data/conf/postfix:/etc/postfix:Z
    - ./data/assets/ssl:/etc/ssl/mail:ro,Z
    - postfix-vol-1:/var/spool/postfix
  environment:
    DBNAME: ${DBNAME}
    DBUSER: ${DBUSER}
    DBPASS: ${DBPASS}
  ports:
    - "25:25"
    - "465:465"
    - "587:587"
  networks:
    - mailcow-network
  restart: unless-stopped
sogo-mailcow
sogo-mailcow:
  image: mailcow/sogo:latest
  depends_on:
    - mysql-mailcow
    - redis-mailcow
  environment:
    DBNAME: ${DBNAME}
    DBUSER: ${DBUSER}
    DBPASS: ${DBPASS}
    MAILCOW_HOSTNAME: ${MAILCOW_HOSTNAME}
  networks:
    - mailcow-network
  restart: unless-stopped
nginx-mailcow
nginx-mailcow:
  image: nginx:alpine
  depends_on:
    - sogo-mailcow
    - rspamd-mailcow
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./data/conf/nginx:/etc/nginx/conf.d:ro,Z
    - ./data/assets/ssl:/etc/ssl/mail:ro,Z
  networks:
    - mailcow-network
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 unbound-mailcow:
5 image: mailcow/unbound:latest
6 volumes:
7 - ./data/hooks/unbound:/hooks:Z
8 - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
9 networks:
10 mailcow-network:
11 aliases:
12 - unbound
13
14 mysql-mailcow:
15 image: mariadb:10.11
16 command: --innodb-buffer-pool-size=256M
17 volumes:
18 - mysql-vol-1:/var/lib/mysql
19 - mysql-socket-vol-1:/var/run/mysqld
20 - ./data/conf/mysql/:/etc/mysql/conf.d/:ro,Z
21 environment:
22 MYSQL_ROOT_PASSWORD: ${DBROOT}
23 MYSQL_DATABASE: ${DBNAME}
24 MYSQL_USER: ${DBUSER}
25 MYSQL_PASSWORD: ${DBPASS}
26 networks:
27 - mailcow-network
28 restart: unless-stopped
29
30 redis-mailcow:
31 image: redis:alpine
32 volumes:
33 - redis-vol-1:/data
34 networks:
35 - mailcow-network
36 restart: unless-stopped
37
38 rspamd-mailcow:
39 image: mailcow/rspamd:latest
40 depends_on:
41 - redis-mailcow
42 volumes:
43 - ./data/conf/rspamd/custom/:/etc/rspamd/custom:Z
44 - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:Z
45 - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:Z
46 - rspamd-vol-1:/var/lib/rspamd
47 networks:
48 - mailcow-network
49 restart: unless-stopped
50
51 dovecot-mailcow:
52 image: mailcow/dovecot:latest
53 depends_on:
54 - mysql-mailcow
55 volumes:
56 - ./data/conf/dovecot:/etc/dovecot:Z
57 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
58 - vmail-vol-1:/var/vmail
59 environment:
60 DBNAME: ${DBNAME}
61 DBUSER: ${DBUSER}
62 DBPASS: ${DBPASS}
63 networks:
64 - mailcow-network
65 restart: unless-stopped
66
67 postfix-mailcow:
68 image: mailcow/postfix:latest
69 depends_on:
70 - mysql-mailcow
71 volumes:
72 - ./data/conf/postfix:/etc/postfix:Z
73 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
74 - postfix-vol-1:/var/spool/postfix
75 environment:
76 DBNAME: ${DBNAME}
77 DBUSER: ${DBUSER}
78 DBPASS: ${DBPASS}
79 ports:
80 - "25:25"
81 - "465:465"
82 - "587:587"
83 networks:
84 - mailcow-network
85 restart: unless-stopped
86
87 sogo-mailcow:
88 image: mailcow/sogo:latest
89 depends_on:
90 - mysql-mailcow
91 - redis-mailcow
92 environment:
93 DBNAME: ${DBNAME}
94 DBUSER: ${DBUSER}
95 DBPASS: ${DBPASS}
96 MAILCOW_HOSTNAME: ${MAILCOW_HOSTNAME}
97 networks:
98 - mailcow-network
99 restart: unless-stopped
100
101 nginx-mailcow:
102 image: nginx:alpine
103 depends_on:
104 - sogo-mailcow
105 - rspamd-mailcow
106 ports:
107 - "80:80"
108 - "443:443"
109 volumes:
110 - ./data/conf/nginx:/etc/nginx/conf.d:ro,Z
111 - ./data/assets/ssl:/etc/ssl/mail:ro,Z
112 networks:
113 - mailcow-network
114 restart: unless-stopped
115
116volumes:
117 mysql-vol-1:
118 mysql-socket-vol-1:
119 redis-vol-1:
120 rspamd-vol-1:
121 vmail-vol-1:
122 postfix-vol-1:
123
124networks:
125 mailcow-network:
126 driver: bridge
127EOF
128
129# 2. Create the .env file
130cat > .env << 'EOF'
131# Hostname
132MAILCOW_HOSTNAME=mail.example.com
133
134# Database
135DBNAME=mailcow
136DBUSER=mailcow
137DBPASS=secure_db_password
138DBROOT=secure_root_password
139
140# Timezone
141TZ=UTC
142EOF
143
144# 3. Start the services
145docker compose up -d
146
147# 4. View logs
148docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/mailcow-full-stack/run | bash

Troubleshooting

  • Database connection errors in dovecot logs: Verify DBPASS environment variable matches MySQL password and mysql-mailcow container is running
  • Redis connection timeouts in rspamd: Check redis-vol-1 volume permissions and ensure Redis container has sufficient memory allocation
  • DKIM verification failures: Regenerate DKIM keys through mailcow admin interface and update DNS TXT records with new public key
  • SOGo calendar sync issues with mobile devices: Verify MAILCOW_HOSTNAME environment variable matches certificate common name and ActiveSync is enabled
  • Mail delivery delays or queue buildup: Check postfix logs for DNS resolution issues and verify sending IP reputation with major providers

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space