Mailcow 自建邮件系统实战:Docker、证书、反代与 DNS
用 Docker 部署 Mailcow 邮件系统:主机名、端口、证书、Nginx 反代、SPF/DKIM/DMARC、备份和常见故障排查。
把密码库放到自己的服务器之后,下一步通常是邮件。Mailcow 把 Postfix、Dovecot、Rspamd、SOGo、Nginx、MariaDB 等组件打包进 Docker,提供完整的收发信、Webmail、日历、联系人和反垃圾能力。它比“装一个 Postfix 再慢慢配”省事,但邮件系统涉及端口、DNS、证书和发信信誉,仍然需要按顺序部署。
先说结论:Mailcow 适合有独立公网 IP、能控制 DNS、愿意维护反垃圾和备份的用户。多数云厂商默认封禁 25 端口,部署前要先确认能否解封,否则只能收信、不能直接向外发信。
一、部署前准备
示例环境:Ubuntu 22.04,域名 mail.example.com,主域名 example.com。实际使用时全部替换成自己的域名和 IP。
| 项目 | 要求 |
|---|---|
| 系统 | Ubuntu 22.04 / Debian 11+,x86_64 |
| 内存 | 最低 2GB,建议 4GB 以上;不足时增加 Swap |
| Docker | Docker Engine 24+,使用 docker compose 插件 |
| 域名 | mail.example.com A 记录指向服务器公网 IP |
| 端口 | 25、465、587、993、995、4190、8080、8443(按需) |
| 反向解析 | 向 VPS 服务商申请 PTR,指向 mail.example.com |
先把主机名设置为完整域名,并写入 hosts,避免 Mailcow 在生成配置和发信时使用错误的主机名:
hostnamectl set-hostname mail.example.com
echo '203.0.113.10 mail.example.com' >> /etc/hosts
hostname -f
ping -c 1 $(hostname -f)
如果系统预装了 Postfix、Exim 或 Sendmail,先停止并禁用,避免占用 25 端口:
systemctl disable --now postfix 2>/dev/null || true
ss -lntp | grep -E ':(25|80|443|8080|8443)\b'
二、安装 Docker 与依赖
不建议使用发行版仓库里的旧 docker.io,Mailcow 对 Docker 版本有要求。使用 Docker 官方仓库安装 Docker CE:
apt update
apt install -y ca-certificates curl gnupg git jq openssl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker
docker --version
docker compose version
如果系统是 Debian,把上面的 linux/ubuntu 换成 linux/debian。看到 Docker 版本至少 24.x,并且 docker compose version 正常输出,就可以继续。

三、克隆 Mailcow 并生成配置
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
./generate_config.sh
脚本会询问邮件主机名和时区。主机名填 mail.example.com,时区填 Asia/Shanghai。如果脚本报 jq: command not found,说明依赖没有装全,执行 apt install -y jq 后重新运行。

生成后会得到 mailcow.conf。先检查主机名、时区和端口。下面是一个常见配置:
MAILCOW_HOSTNAME=mail.example.com
TZ=Asia/Shanghai
HTTP_PORT=8080
HTTPS_PORT=8443
如果服务器上已经有宝塔、1Panel 或其他 Nginx 占用 80/443,就把 Mailcow 内部 HTTP/HTTPS 改成 8080/8443,再让外部 Nginx 反代。不要让两个服务同时抢 80/443。
四、启动容器
首次启动会拉取十几个镜像,时间取决于网络:
cd /opt/mailcow-dockerized
docker compose pull
docker compose up -d
docker compose ps
等到所有容器都是 running/healthy。Mailcow 组件较多,2GB 内存的机器容易在启动或反垃圾扫描时 OOM;内存不足可以临时增加 Swap,但不建议长期把邮件系统跑在严重超卖的机器上。

五、证书配置
Mailcow 内部 Nginx 使用 data/assets/ssl/cert.pem 和 key.pem。可以在宝塔或 1Panel 申请 Let’s Encrypt 证书,然后把完整证书链和私钥写进去:
cd /opt/mailcow-dockerized/data/assets/ssl
cp cert.pem cert.pem.bak
cp key.pem key.pem.bak
nano cert.pem
nano key.pem
chmod 600 cert.pem key.pem
chown root:root cert.pem key.pem
docker compose restart nginx-mailcow
证书文件必须是完整链,私钥必须和证书匹配。续签问题同样要注意:面板续签后不会自动更新 Mailcow 的这两个文件,需要在续签后复制并重启 nginx-mailcow,或者用脚本把证书同步到该目录。

六、外部 Nginx 反向代理(可选)
Mailcow 自带 Nginx,如果 80/443 没有被占用,可以直接用它的 8443。若主机上已经有宝塔 Nginx,建议让外部 Nginx 监听 443,再代理到 Mailcow 的 8443:
nano /etc/nginx/sites-available/mail.example.com
server {
listen 80;
server_name mail.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mail.example.com;
ssl_certificate /etc/letsencrypt/live/mail.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 0;
location / {
proxy_pass https://127.0.0.1:8443;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600;
}
}
启用并测试:
ln -s /etc/nginx/sites-available/mail.example.com /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
proxy_ssl_verify off 只用于 Mailcow 内部自签/内部证书的场景;如果你已经把有效证书放进 Mailcow,也可以按需开启校验。外部 Nginx 的证书和 Mailcow 内部证书可以分别管理。

七、DNS 记录
邮件能不能正常收发,DNS 比容器更关键。添加域名之前,先在 DNS 服务商处准备以下记录:
| 主机名 | 类型 | 值 | 说明 |
|---|---|---|---|
mail.example.com |
A | 服务器公网 IPv4 | 邮件主机名 |
example.com |
MX | mail.example.com,优先级 10 |
收信入口 |
example.com |
TXT | v=spf1 mx ~all |
SPF,按需加 ip4 |
dkim._domainkey.example.com |
TXT | Mailcow 后台生成 | DKIM 签名 |
_dmarc.example.com |
TXT | v=DMARC1; p=quarantine; rua=mailto:[email protected] |
DMARC 策略 |
autodiscover.example.com |
CNAME | mail.example.com |
客户端自动配置 |
autoconfig.example.com |
CNAME | mail.example.com |
客户端自动配置 |
| IP 反向解析 | PTR | mail.example.com |
向 VPS 服务商申请 |
DKIM 记录要等域名添加后再生成。修改 DNS 后用 dig 检查:
dig +short MX example.com
dig +short TXT example.com
dig +short TXT dkim._domainkey.example.com
dig +short TXT _dmarc.example.com
八、初始化 Mailcow
浏览器访问 https://mail.example.com(或 https://服务器IP:8443)。默认管理员账号是 admin,密码是 moohoo,登录后立刻修改密码并开启两步验证。

进入「Configuration → Mail Setup → Domains → Add Domain」,这里填写顶级域名 example.com,不要填 mail.example.com。主机名和邮件域名是两个概念。

添加后点击域名右侧的 DNS 按钮查看检测结果。Mailcow 的检测可以作为参考,但不要盲目照抄;以实际 DNS 记录和邮件日志为准。

接着创建邮箱、别名和配额。新邮箱默认使用主域名,SMTP/IMAP 客户端可以手动填写:
SMTP:mail.example.com,587(STARTTLS)或 465(SSL)
IMAP:mail.example.com,993(SSL)
用户名:完整邮箱地址
九、端口、发信与云厂商限制
要让外部把邮件投递进来,入站 25 必须可达;客户端提交用 587/465;IMAP 用 993;Sieve 用 4190。出站 25 经常被云厂商封禁,表现是“能收不能发”或队列长期重试。
- 向服务商提交工单,申请解封 TCP 25 出站;
- 如果无法解封,使用 Mailcow 的 relayhost 转发到可信 SMTP 中继;
- 检查 PTR 是否指向
mail.example.com; - SPF、DKIM、DMARC 三项至少先完成前两项;
- 不要用住宅 IP 或动态 IP 直接发信,信誉会很差。
十、常见问题与排查
| 现象 | 排查方向 |
|---|---|
| 启动时报 80/443 被占用 | 主机已有 Nginx/宝塔;把 HTTP_PORT/HTTPS_PORT 改为 8080/8443,或停掉冲突服务。 |
jq: command not found |
apt install -y jq 后重新执行 ./generate_config.sh。 |
| 提示 Docker 版本过低 | 卸载 docker.io,按官方 Docker CE 仓库安装 24+ 版本。 |
| 证书不生效或提示不安全 | 检查 cert.pem/key.pem 是否为完整链、是否匹配、权限是否 600,重启 nginx-mailcow。 |
| 面板 502 / 拒绝连接 | docker compose ps、docker compose logs nginx-mailcow、内存是否不足、端口映射是否正确。 |
| 能收不能发 | 25 出站是否被封、PTR/SPF/DKIM 是否配置、是否进入 Rspamd 队列。 |
| 忘记管理员密码 | docker compose exec php-fpm-mailcow php /web/src/reset-admin-password.php |
| DNS 检测不通过 | 用 dig 直接查 MX/TXT/PTR,确认没有代理 Cloudflare 的邮件记录,等待 TTL 生效。 |

十一、备份、更新与安全
Mailcow 自带备份脚本,备份前先确认磁盘空间:
cd /opt/mailcow-dockerized
./helper-scripts/backup_and_restore.sh backup all
至少备份 data/ 和 mailcow.conf;把备份放到另一台机器或对象存储,并定期做恢复演练。升级使用官方脚本:
cd /opt/mailcow-dockerized
./update.sh
安全方面:修改默认管理员密码、开启 2FA、限制管理后台访问来源、保持 Fail2ban 开启、不要公开数据库端口、配置 DMARC,并定期检查邮件队列和 Rspamd 日志。
十二、写在最后
Mailcow 把邮件系统最难缠的部分封装成了容器,但“能启动”不等于“能稳定收发”。真正决定成败的是主机名、25 端口、PTR、SPF/DKIM/DMARC、证书续签和备份。按本文顺序部署,先把收信和 Web 面板跑通,再处理发信信誉,排错会轻松很多。
参考资料与图片出处
本文根据 O Meow 的原文《📧 别再租企业邮了!喵教你自托管 Mailcow,全功能邮件系统带 Web 界面》整理重写,原文地址:https://www.oops.net.cn/115/。
部署截图、Mailcow 登录页、添加域名和 DNS 检测截图均来自上述原文。图片版权归原作者,仅用于本文说明;未经授权请勿转载图片。
讨论
暂无评论