使用 Maddy & Snappymail 自建域名邮箱
目录
虽然谷歌的无限别名很好用,但终归还是有自己的域名邮箱是更方便的。
网上看过一圈解决方案,有很多一站式的方案看起来很不错,比如说 poste.io,mailu.io 以及 mailcow 等,它们都提供 docker 解决方案,不过对于我而言,还是更倾向于使用开源的解决方案,而不是免费的解决方案。最终发现 maddy 项目能满足我的需求,它基于 GPL-3.0 开源协议,使用 Golang 开发,性能有保障,同时选用非开源的 SnappyMail 作为前端,等能找到更好的开源 mailbox 前端之前,先暂时选定它了。
本文假设读者已经拥有了自己的域名,并且拥有自己的能运行 docker & docker compose 的云环境。
准备工作 #
检查 25 端口是否开放 #
使用下面的命令检测你将要部署的 VPS 是否开放了 25 端口:
telnet smtp.qq.com 25
如果类似下面的显示则说明成功,否则代表不行,需要工单或者换其他的 VPS
telnet smtp.qq.com 25
Trying 1xxx.xxx.xxx.xxx...
Connected to smtp.qq.com.
Escape character is '^]'.
220 smtp.qq.com Esmtp QQ Mail Server
配置域名 DNS #
记录类型 | 域名 | 值 |
---|---|---|
A | 服务器ipv4地址 | |
AAAA | 服务器ipv6地址(可选) | |
A | mx | 服务器ipv4地址 |
AAAA | mx | 服务器ipv6地址(可选) |
MX | @ | mx.yourdomain.com |
TXT | @ | v=spf1 mx ~all |
TXT | mx | v=spf1 mx ~all |
TXT | _dmarc | v=DMARC1; p=quarantine; ruf=mailto:[email protected] |
TXT | _mta-sts | v=STSv1; id=1 |
TXT | _smtp._tls | v=TLSRPTv1;rua=mailto:[email protected] |
TXT | default._domainkey | *稍后请根据后文生成的内容填写 |
- mail 域名用作 web 前端,mx 域名用作邮件发送域名
- @代表你的二级域名,类似 yourdomain.com
- [email protected] 可以根据你的实际情况调整,后续部署好实例后需要创建相应账号
将除了 default._domainkey
的 DNS 配置好后,就可以进入到部署环境了
部署 #
创建数据卷 #
为保证数据不跟随容器销毁,我们提前创建好接下来需要使用的 volume
docker volume create maddydata
docker volume create snappymail-data
获取证书 #
请自行使用合适的工具获取证书,本文使用的 certbot
配置 docker-compose 文件 #
mkdir -p /opt/mail && cd /opt/mail
nano docker-compose.yml
写入下面的 docker compose 文件
version: "3.8"
services:
maddy:
image: foxcpp/maddy:latest
ports:
- "25:25"
# - "143:143"
# - "587:587"
# - "993:993"
volumes:
- maddydata:/data
- /etc/letsencrypt/archive/mx.yourdomain.com/:/data/tls/
environment:
# REPLACE DOMAINS WITH YOURS
- MADDY_HOSTNAME=mx.yourdomain.com
- MADDY_DOMAIN=yourdomain.com
deploy:
replicas: 1
resources:
limits: { cpus: '0.2', memory: '32M' }
reservations: { cpus: '0.05', memory: '16M' }
snappymail:
image: ratneo/snappymail
ports:
- '127.0.0.1:38888:8888'
volumes:
- snappymail-data:/snappymail/data
depends_on:
- maddy
deploy:
resources:
limits: { cpus: '0.2', memory: '64M' }
reservations: { cpus: '0.05', memory: '32M' }
volumes:
maddydata:
external: true
snappymail-data:
external: true
- 注意将文件里的域名换做你自己的域名
- 你肯定注意到了 maddy 常用的端口也被注释掉了,理论上如果你和我一样,只想通过 SnappyMail 提供的网页端访问,则保持注释,如果你想用第三方客户端连接你的邮箱,如 Outlook,则请将 587 和 993 端口开放。
启动服务
docker compose up -d
修改 maddy.conf 配置文件 #
cd $(docker volume inspect maddydata --format '{{.Mountpoint}}')
nano maddy.conf
确保证书文件路径和前面映射的相同
tls file /data/tls/fullchain1.pem /data/tls/privkey1.pem
重启 docker 服务
cd /opt/mail
docker compose restart
获取 DKIM 密钥 #
cd $(docker volume inspect maddydata --format '{{.Mountpoint}}')
cat dkim_keys/yezim.com_default.dns
生成的内容写入到 DNS 表中最后一个 default._domainkey 的值里
创建邮箱管理用户 #
docker exec -it mail-maddy-1 /bin/bash
maddyctl creds create [email protected]
maddyctl imap-acct create [email protected]
配置 nginx 反向代理 #
nano /etc/nginx/conf.d/mail.conf
下面是反向代理的样例
server {
server_name mail.yourdomain.com;
# Security / XSS Mitigation Headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
location / {
proxy_redirect 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_pass http://127.0.0.1:38888/;
}
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mail.yourdomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name mail.yourdomain.com;
return 404; # managed by Certbot
}
请根据你的实际情况自行编辑nginx反向代理配置
邮箱设置 #
登陆 SnappyMail 管理员页面,并编辑域名:https://mail.yourdomain.com/?admin/domains,默认用户名为 admin 密码在需要到挂载卷里取得,命令如下:
cd $(docker volume inspect snappymail-data --format '{{.Mountpoint}}')
cat ./_data_/_default_/adminpassword.txt
请务必修改为强密码
添加域名,在服务器一列请填写 maddy
并指定IMAP端口为 993,SMTP 端口为 465,同时加密都选为 SSL/TLS。
注:填写 maddy 的原因是使用 docker-compose 的 network 机制,在不暴露端口的情况下访问到 docker 实例
Cloudflare Zero Trust(可选) #
虽然我们给 SnappyMail 设置了强密码,但为了确保更安全,建议使用 Cloudflare Zero Trust 的机制保护我们的邮箱网页。 步骤为:
- 点亮 Cloudflare 小云朵
- 在 Zero Trust 的 Access 中添加 application,并指定保护策略
限于篇幅,此处就不再深入描述,作为一个安全提示