Mailcow 日常运维手册
Mailcow 日常运维手册:DKIM/SPF/DMARC 三件套核查(含 Gmail 550-5.7.26 DMARC 拒收真实回显)、队列管理与退信排查、证书续期、官方脚本全量备份与恢复实测、组件日志定位方法与低配降配资源基线,全部基于 2026-09a 实测。
Mailcow 日常运维手册
适用:按部署指南篇完成的 Mailcow 2026-09a 环境(本域
example.com、主机名mail.example.com、降配运行)。本文覆盖 DNS 三件套核查、队列与退信、证书、备份恢复、日志排障、资源基线与升级,全部操作于 2026-10-19 实测,回显真实。
一、环境信息
- Mailcow 2026-09a,18 个服务容器(
SKIP_CLAMD/SOGO/FTS=y降配,clamd/sogo 容器仅保活) - 管理端
http://mail.example.com:8126/admin(HTTPS 8130),REST API 已启用 - 演示邮箱
demo@example.com;本地收发实测详见快速入门篇
二、DKIM/SPF/DMARC 三件套核查
邮件身份三件套各自独立:DKIM(信件签名)、SPF(发信 IP 授权)、DMARC(前两者的策略聚合)。Mailcow 内 Rspamd 对每封入站信执行三项检查并把结果写进 Authentication-Results 头,这是运维核查的第一现场。
2.1 从 Authentication-Results 头核查
入站信实测头(快速入门篇 5.2 的外域来信):
Authentication-Results: mail.example.com;
none
X-Rspamd-Queue-Id: 3CCE6108C313
结果语义速查:pass(通过)/fail(失败,后跟策略原因)/none(对方未发布该记录)/temperror/permerror。X-Spamd-Result 中的 DKIM_TRACE、SPF、DMARC 符号给出逐条得分明细。
2.2 本域三件套的发布侧核查
DKIM(部署时自动生成,选择器 dkim):
$ curl -s -H "X-API-Key: <API_KEY>" http://127.0.0.1:8126/api/v1/get/dkim/example.com | python3 -c "import json,sys; print(json.load(sys.stdin)['pubkey'][:40], '...')"
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgK...
需在 DNS 发布三条 TXT 记录(公网上线前的核对清单):
| 记录 | 值 |
|---|---|
dkim._domainkey.example.com | v=DKIM1;k=rsa;p=<公钥> |
example.com | v=spf1 mx -all(按实际发信源裁剪) |
_dmarc.example.com | v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com |
2.3 真实公网验证案例:Gmail 的 DMARC 硬拒收
本环境出站 25 端口连通公网时,向 Gmail 发送一封本域认证信(SPF/DKIM/DMARC 均未对外发布),对方 MTA 直接拒收,postfix 日志实测回显:
postfix/smtp: 5A229108C279: to=<postmaster@gmail.com>, relay=gmail-smtp-in.l.google.com[192.178.163.27]:25,
delay=12, delays=2.7/0/8.8/0.49, dsn=5.7.26, status=bounced
(host gmail-smtp-in.l.google.com said: 550-5.7.26 Unauthenticated email from example.com is not accepted
due to 550-5.7.26 domain's DMARC policy. ... - gsmtp (in reply to end of DATA command))
结论可量化:主流接收方对"无 DMARC 发布 + 无对齐签名"的域已从垃圾评分走向硬拒(dsn=5.7.26)。自托管域上线前把三件套配齐不是最佳实践,是准入门槛。
2.4 DNS 检查入口
管理端 Status → DNS 状态页对每个域名给出 MX/SPF/DMARC/DKIM 的核对面板;命令行可用 Mailcow 自带 Unbound 递归解析复核公网记录(docker exec mailcowdockerized-unbound-mailcow-1 unbound-host -C /etc/unbound/unbound.conf -t TXT example.com)。
三、队列管理与退信排查
3.1 队列查看与清理(postfix 容器内)
$ docker exec mailcowdockerized-postfix-mailcow-1 postqueue -p
Mail queue is empty
$ docker exec mailcowdockerized-postfix-mailcow-1 postqueue -f # 立即重投
$ docker exec mailcowdockerized-postfix-mailcow-1 postsuper -d ALL deferred # 清空延迟队列
3.2 立即退信(bounce)实测:收件域不存在
向保留 TLD 发信(DNS NXDOMAIN),全链路日志:
postfix/submission/smtpd: warning: Unable to look up MX host example.invalid
for Recipient address unreachable@example.invalid: Name or service not known
postfix/qmgr: 56793108C2EB: from=<demo@example.com>, size=480, nrcpt=1 (queue active)
postfix/smtp: 56793108C2EB: to=<unreachable@example.invalid>, relay=none, delay=1.3,
delays=1.3/0.03/0/0, dsn=5.4.4, status=bounced
(Host or domain name not found. Name service error for name=example.invalid type=AAAA: Host not found)
要点:NXDOMAIN 属硬错(dsn=5.4.4),立即 status=bounced 并向发件人回 NDR,不进延迟队列;postqueue -p 复查仍为空。会进 deferred 的是连接超时/4xx 类软错(如对方 MTA 拒网),此时队列里可见 *** deferred 条目与重试计划。
3.3 垃圾邮件隔离与学习
入站判垃圾的邮件按域名策略进入隔离(管理端 E-Mail → Mailu 类隔离界面在 Rspamd 面板),用户端在 Webmail/隔离通知里处理;误判样本可用 helper-scripts/reset-learns.sh 重置 Rspamd 贝叶斯学习状态。
四、证书管理
- 生成脚本默认产出 snake-oil 自签证书(无公网时的兜底,浏览器会有告警)。
- 公网上线:
SKIP_LETS_ENCRYPT=n后 acme-mailcow 容器自动走 HTTP-01 为MAILCOW_HOSTNAME及各 ADDITIONAL_SAN 签发并自动续期;80/443 不可直连时用 2026-03 版本引入的 DNS-01(ACME_DNS_CHALLENGE=y+ACME_DNS_PROVIDER+ 提供商凭据)。 - 手动替换证书:放置全链证书到
data/assets/ssl/cert.pem与key.pem后docker compose restart postfix-mailcow dovecot-mailcow nginx-mailcow。 - 证书到期巡检:
helper-scripts/expiry-dates.sh列出各服务当前证书有效期。
五、备份与恢复(官方脚本实测)
5.1 全量备份
$ mkdir -p /opt/data/mailcow-backup
$ export MAILCOW_BACKUP_LOCATION=/opt/data/mailcow-backup
$ printf 'y\n' | bash helper-scripts/backup_and_restore.sh backup all
脚本以官方 ghcr.io/mailcow/backup:latest 工具镜像运行,逐组件打包(mariadb 用 xtrabackup 二进制备份)。实测产物:
$ ls -lh /opt/data/mailcow-backup/mailcow-2026-10-19-21-55-23/
-rw-r--r-- 1 root root 459 backup_crypt.tar.zst
-rw-r--r-- 1 root root 3.7M backup_mariadb.tar.zst
-rw-r--r-- 1 root root 7.0K backup_postfix.tar.zst
-rw-r--r-- 1 root root 32K backup_redis.tar.zst
-rw-r--r-- 1 root root 1.2M backup_rspamd.tar.zst
-rw-r--r-- 1 root root 12K backup_vmail.tar.zst
-rw------- 1 root root 12K mailcow.conf
六个 tar.zst 覆盖 crypt(密钥卷)/mariadb/postfix/redis/rspamd/vmail(Maildir 邮件存储),外加 mailcow.conf(含全部随机密钥,务必随份保管)。单组件备份把 all 换成 vmail|crypt|redis|rspamd|postfix|mysql;--delete-days N 清理过期份。生产建议 cron 日备 + 异机存放。
5.2 恢复
$ printf 'y\n' | bash helper-scripts/backup_and_restore.sh restore /opt/data/mailcow-backup/mailcow-2026-10-19-21-55-23/backup_vmail.tar.zst
按组件单包恢复;整机迁移 = 新机部署同版本 Mailcow + 逐包 restore + 恢复 mailcow.conf。另有 create_cold_standby.sh 做冷备同步。
六、日志排障(真实案例)
6.1 组件日志入口
$ docker compose logs --tail=100 postfix-mailcow # SMTP 收发/队列
$ docker compose logs --tail=100 dovecot-mailcow # IMAP/认证/投递
$ docker compose logs --tail=100 rspamd-mailcow # 反垃圾判定
$ docker compose logs --tail=100 unbound-mailcow # DNS 解析
管理端 System → Logs 提供同样的检索界面。
6.2 案例:IMAP 认证失败定位
用 IMAP 客户端登录报 AUTHENTICATIONFAILED,dovecot 日志精确定位:
dovecot: auth-worker: lua(demo@example.com,10.89.54.1,<ioE+xjFerL4KWTYB>):
Password mismatch (SHA1 of given password: c09f2a)
dovecot: imap-login: Disconnected: Aborted login by logging out (auth failed, 1 attempts in 2 secs):
user=<demo@example.com>, method=PLAIN, rip=10.89.54.1, lip=10.89.54.250, TLS, TLSv1.3 ...
排障路径:auth-worker ... Password mismatch → 客户端发送的密码与库中哈希不符(日志给出收到的密码 SHA1 前缀便于与本地比对,本例定位为客户端把行尾空白一并编码)。管理员侧核对哈希用:
$ docker exec mailcowdockerized-dovecot-mailcow-1 doveadm pw -t '<库中哈希>' -p '<待验证口令>'
(verified) # 匹配回显
6.3 案例:收发链路追踪
一封信的完整旅程按 queue id 串起(submission 收入 → cleanup 头部规范化 → qmgr → smtp/lmtp 投递):
postfix/submission/smtpd: 519ED108C2FE: client=unknown[10.89.54.1], sasl_method=LOGIN, sasl_username=demo@example.com
postfix/cleanup: 519ED108C2FE: message-id=<20261019214841.890411@ops>
postfix/qmgr: 519ED108C2FE: from=<demo@example.com>, ... (queue active)
dovecot: lmtp(demo@example.com): sieve: msgid=<...>: stored mail into mailbox 'INBOX'
入站在 postfix 日志按 X-Rspamd-Queue-Id(如 3CCE6108C313)串联 Rspamd 判定结果。
6.4 自动发现类报错
宿主未解析 autodiscover.*/autoconfig.* 时客户端反复探测,nginx access 日志出现高频 404;内网环境在 /etc/hosts/内网 DNS 补记录即可(见部署指南篇 6.4)。
七、资源基线(降配部署实测)
稳态空载实测(docker stats --no-stream,按内存降序):
NAME MEM USAGE CPU %
mailcowdockerized-ofelia-mailcow-1 795.4MiB 0.00%
mailcowdockerized-mysql-mailcow-1 233.1MiB 0.00%
mailcowdockerized-rspamd-mailcow-1 135.6MiB 0.09%
mailcowdockerized-dovecot-mailcow-1 85.23MiB (投递瞬时高)
mailcowdockerized-sogo-mailcow-1 73.65MiB 0.00% # 降配保活
mailcowdockerized-postfix-mailcow-1 63.66MiB 0.01%
mailcowdockerized-dockerapi-mailcow-1 58.36MiB 0.20%
mailcowdockerized-php-fpm-mailcow-1 50.63MiB 0.01%
mailcowdockerized-netfilter-mailcow-1 36.51MiB 0.01%
mailcowdockerized-unbound-mailcow-1 35.48MiB 0.05%
mailcowdockerized-postfix-tlspol-mailcow-1 27.96MiB
mailcowdockerized-watchdog-mailcow-1 23.01MiB 0.32%
mailcowdockerized-olefy-mailcow-1 14.85MiB
mailcowdockerized-nginx-mailcow-1 13.65MiB
mailcowdockerized-redis-mailcow-1 10.75MiB
mailcowdockerized-acme-mailcow-1 5.812MiB
mailcowdockerized-clamd-mailcow-1 3.438MiB # 降配保活
mailcowdockerized-memcached-mailcow-1 1.953MiB
量化结论:降配(SKIP_CLAMD/SOGO/FTS)后全栈稳态 RSS 约 1.3–1.7 GiB(ofelia 统计含页缓存偏高),6 GiB 可用内存的宿主机部署后仍有充足余量;开启 ClamAV 后需另计约 1 GiB 量级的病毒库内存。watchdog 容器持续探测各组件(WATCHDOG_NOTIFY_START=y 默认开),异常自愈与通知在 System → Configuration → Rspamd/Watchdog 面板配置。
八、版本升级
官方升级通道为仓库内 update.sh(自动拉取新 compose/镜像、执行数据库迁移、支持 --check 预检)。纪律:
- 升级前先做 5.1 全量备份;
- 固定 tag 部署的场合,升级即
git fetch --tags && git checkout <新 tag>后运行update.sh; - 每月 Release 附 Revision 时优先跟到 Revision 最新(安全修复累积);
nightly分支不建议用于生产。