跳到正文
LUNA.TEL创造,创新,有爱。
技术 阅读约 8 分钟

Mailcow 自建邮件系统实战:Docker、证书、反代与 DNS

用 Docker 部署 Mailcow 邮件系统:主机名、端口、证书、Nginx 反代、SPF/DKIM/DMARC、备份和常见故障排查。

砂糖橘猫 26.10.2026 暂无评论

把密码库放到自己的服务器之后,下一步通常是邮件。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 正常输出,就可以继续。

docker version 输出版本号
先确认 Docker 版本满足 Mailcow 要求。图片来自原文。

三、克隆 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 后重新运行。

安装 jq 依赖后重新执行 Mailcow 配置脚本
generate_config.sh 依赖 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 所有容器正常运行
docker compose ps 中所有 Mailcow 容器正常运行。图片来自原文。

五、证书配置

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,或者用脚本把证书同步到该目录。

宝塔面板 SSL 证书部署成功界面
面板申请证书后,把证书链和私钥写入 Mailcow 的 SSL 目录。图片来自原文。

六、外部 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 内部证书可以分别管理。

nginx -t 配置测试通过
nginx -t 通过后再 reload。图片来自原文。

七、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,登录后立刻修改密码并开启两步验证。

Mailcow 管理后台登录页面
Mailcow 登录页。图片来自原文。

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

Mailcow 添加顶级域名界面
Add Domain 填顶级域名。图片来自原文。

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

Mailcow 域名列表与 DNS 检测按钮
域名列表中的 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 提示 Docker 版本过低
Docker 版本过低时的报错,需要安装 Docker CE 新版本。图片来自原文。

十一、备份、更新与安全

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 检测截图均来自上述原文。图片版权归原作者,仅用于本文说明;未经授权请勿转载图片。

Mailcow 项目:https://github.com/mailcow/mailcow-dockerized

作者

砂糖橘猫

生物专业。业余研究网络技术,通讯技术,银行业。业余无线电A类证书,呼号BG2GSM。精通英语,俄语,想学日语,德语。

4 篇文章 全部文章

讨论

暂无评论

发表评论

邮箱不会公开。带 * 的为必填项。

人机验证

由 Cloudflare Turnstile 提供保护。