使用 mox 给现有服务器部署邮件服务器
Mox是一个比较新的用 go 写的邮件服务器,自家宣传用语是:
modern, secure, all-in-one email server
Stay in control of your email and keep email decentralized!
这篇文章是对部署过程的回顾,用以记录部署中出现的难点。这次部署有一些先决条件,导致了我遇到了一些没想到的困难
-
使用现有 VPS 服务器来部署,而不是 mox 官方推荐的单独域名,单独服务器的架构。因为 mox 比较傻瓜式,所以自带了给域名更新 SSL certificate 的机制,还有会自动检测使用端口,不需要你额外设置。这也就意味想要 customize 就需要花费更多精力去研究傻瓜式背后隐藏着什么。
-
使用现有域名,域名供应商官方页面只有很少的 DNS record 管理功能。而如果想绑定 mox 邮件服务器到自己的域名,需要通过在自己的域名服务商录入相应的 DNS 来完成的。所以你需要有相应的手段来批量更新自己的 DNS。
所以你如果条件差不多,也想给自己的小服务器添一个邮箱功能的话,这篇文章就是来摘除那些疑难杂症的。如果你有单独的服务器,并且有一个自己的域名,那么可以按照官方文档,直接下载并安装 mox,一键 ./mox quickstart you@example.com
解决所有问题(官方这么说的,不是我
安装 mox,初始设置
登陆自己的服务器,使用 root 身份,执行以下命令:
# Create mox user and homedir (or pick another name or homedir):
# 创建用户 mox 身份,并给 mox 文件夹里找个家
useradd -m -d /home/mox mox
从下载页面找到最新的 mox binary 链接,拷贝以后下载到对应文件夹里,并开始设置:
# 进入对应文件夹
cd /home/mox
# example downloading the version 0.0.14 with go version 1.24.2
curl https://beta.gobuilds.org/github.com/mjl-/mox@v0.0.14/linux-amd64-go1.24.2/0EOudM9R9g0KUO2yqQO6fO1yjEW8/mox-v0.0.14-go1.24.2
# setup execute permission
chmod +x mox-v0.0.14-go1.24.2
# link command (1)
ln -s mox-v0.0.14-go1.24.2 mox
# quick check - should give you the version and go version
./mox version
# config (2)
./mox quickstart -existing-webserver admin@paomian.de
- 这里软连接了
mox
和mox-v0.0.14-go1.24.2
,下面用./mox
就可以直接用了,不用输入那个原始名字了 - 注意 ⚠️ 这里用了一个 flag
-existing-webserver
,因为是给已经运行的机器部署 mox。这就是告诉 mox,不要自己监听 80 和 443 端口,我自己会帮你设置。
mox 接下来会生成一堆配置文件,如果你的 terminal 看起来不方便,在文件夹的下面有一个quickstart.log
,会记录这个。但要记住这个是会被覆盖的,下次你再设置的时候,生成的内容会重新写在这个里面,导致前面的消失。一定要在第一次的时候把这个文件内容拷贝下来,里面包含有一次性消息,比如给你设置的初始邮箱密码,管理员密码等。
下面给出一些生成的信息例子,注释用数字标出,后面有解释:
Checking if DNS resolvers are DNSSEC-verifying...
WARNING: It looks like the DNS resolvers configured on your system do not
verify DNSSEC...
Recommended action: Install unbound, a DNSSEC-verifying recursive DNS resolver,
ensure it has DNSSEC root keys (see unbound-anchor), and enable support for
"extended dns errors" (EDE, available since unbound v1.16.0, see below; not
required, but it gives helpful error messages about DNSSEC failures instead of
generic DNS SERVFAIL errors). Test with "dig com. ns" and look for "ad"
(authentic data) in response "flags".
(1)
...
NOTE: It looks like the DNS records of your domain (zone) are not DNSSEC-signed.
Mail servers that send email to your domain, or receive email from your domain,
cannot verify that the MX/SPF/DKIM/DMARC/MTA-STS records they receive are
authentic. DANE, for authenticated delivery without relying on a pool of
certificate authorities, requires DNSSEC, so will not be configured at this
time.
(2)
...
Checking if outgoing smtp connections can be made by connecting to gmail.com mx on port 25... OK
Checking whether host name IPs are listed in popular DNS block lists... OK
(3)
Admin password: xxxxxxxxxxxxx
Placeholder paths to TLS certificates to be provided by the existing webserver
have been placed in config/mox.conf and need to be edited.
No private keys for the public listener have been generated for use with DANE.
To configure DANE (which requires DNSSEC), set config field HostPrivateKeyFiles
in the "public" Listener to both RSA 2048-bit and ECDSA P-256 private key files
and check the admin page for the needed DNS records.
(4)
....
You must configure your existing webserver to forward requests for:
https://mta-sts.paomian.de/
https://autoconfig.paomian.de/
To mox, at:
http://127.0.0.1:81
(5)
...
The DNS records to add:
(6)
...
- 检查服务器的 DNS-resolver,发现没有 DNSSEC 设置,鼓励你安装 unbound,一个可以支持 DNSSEC 的 本地 DNS-resolver。
- 检查域名的 DNS 证书,发现没有 DNSSEC 相关设置,也就没办法设置 DANE。DANE 是在 DNSSEC 基础上的,确保邮件分发安全,但是又不需要 SSL 认证的一种新协议。
- 检查 25 通用邮件端口,以及域名所在的 IP 现在有没有被列为垃圾邮件发送地址——有专门的记录相关 IP 地址声誉的网站,如果声誉过差,就会被标记,进而可能被所有邮件服务器拒绝,所以你域名绑定的 IP 地址如果这时已经声誉过差了,建议赶快跟你的服务器商协商,换一个。
- 给定管理员密码——可以通过管理员页面登录。相关 TLS 的设置已经在
mox.conf
里准备好了,只需要给出 key 的相关路径。同时再次提醒,因为没有 DNSSEC,所以也就没有设置 DANE 的私钥。 - 因为是已经存在的服务器,上面可能在不同的端口运行的不同的服务,所以需要把 mox 相关的请求转给相关的端口。
- 需要给 DNS 加上的记录,下面一大片都是。
可以看到里面给出的建议已经很详细了,下面就需要一点点克服。需要完成的有以下几点:
- 配置 mox。设置公共 IP 地址,设置 TLS 的证书等
- 配置 DNSSEC。安装 unbound 来实现。
- 配置 DNS records。需要给自己的域名供应商提供并写入一系列需要的 DNS records。
- 配置 proxy。因为是用了 reverse proxy,所以需要把相应的服务桥接到 mox 配置里的 port 上。
更改 mox 配置
因为是给一个已经存在的网站配置 mox,所以你的服务器现在应该已经有了自己的域名,固定的 IP 地址,以及 TLS certificates。可以参考如何给自己 host 的网站设置 subdomain 并加上 SSL来取得相关配置和证书。
首先 su -
切到 root 模式,进入 /home/mox/config
,vim 打开/home/mox/config/mox.conf
,开始配置,需要改的点如下:
# Full hostname of system, e.g. mail.<domain>
Hostname: 你自己的域名,比如 paomian.de
...
Listeners:
public:
IPs:
- xxx.xxx.xxx.xxx (改成你VPS供应商给你的固定IP)
# For SMTP/IMAP STARTTLS, direct TLS and HTTPS connections. (optional)
TLS:
KeyCerts:
-
# Certificate including intermediate CA certificates, in PEM format.
CertFile: /home/www-data/certs/paomian.de/fullchain.pem
# Private key for certificate, in PEM format. PKCS8 is recommended, but PKCS1 and
# EC private keys are recognized as well.
KeyFile: /home/www-data/certs/paomian.de/key.pem
HostPrivateKeyFiles:
- /home/mox/config/key.pem
注意在 TLS 里面需要给出你用的 TLS 证书和密钥的路径,这一套是你的网站用来 https 连接时用的,走的是 CA 认证的那一套。然后在HostPrivateKeyFiles
里面,你可以自己生成一个私钥,这个是用来走 DANE 和 DNSSEC 认证那一套,下一章会解释这些是什么。
另外需要注意的点:
- mox 自带的 web interface 设置
- AdminHTTP: port xxx
- WebmailHTTP: port xxx
- 这里的 port xxx, 就是 mox 自带的 web interface 接口,如果想用,可以 ssh 你的本地机器的接口到这些接口上,然后就可以在本地的浏览器使用了
- autoconfiguration/autodiscovery
- Port: xxx 就是后面你需要在 nginx 里面设置的桥接 port,有的邮件客户端会自动请求你域名下的
autoconfig.你的域名
,来配置邮箱。这样有请求抵达autoconfig.你的域名
,后会自动转到你所设置的这个 port 下面。
- Port: xxx 就是后面你需要在 nginx 里面设置的桥接 port,有的邮件客户端会自动请求你域名下的
- MTASTSHTTPS
- Port: xxx 跟上面一样,也是外部可能会发起的请求要映射的 port 设置,需要我们把收到的 MTA-STS 请求桥接在这个 port 上。
安装 unbound
why 为什么?DNESSEC & DANE
为什么要安装这个东西呢?一个本地的支持 DNSSEC 的 DNS-resolver 到底是干什么的?这就关乎到 DNSSEC 又是何方神圣。简单理解的话, DNSSEC 是给 DNS 的客户端用来确保 DNS 被解析的时候,返回来的数据是真实的,而不是网络上随便一个人发出来骗你的。这套安全机制包含两个大的方面,第一,存放在 DNS 目录上的记录被 DNSSEC-signed 了,相当于给这些公开记录盖一个印章。第二,本地的支持 DNSSEC 的 DNS-resolver 可以通过这些印章认清那些返回的 DNS records 是真实的,进而相信那些结果。
而如何验证这些记录被 signed 了呢?如果你了解 certificate authoriy (CA)机制的话,那里面是引入了第三方验证机构,但是这些年的发展让 CA 不堪重负,并且一旦一个 CA 被侵入的话,影响的就是一大片它所认证的记录。DANE 就是在这种情况下被提出来的,用来取代 CA,不用第三方机构,而是采取在 DNS 的记录上面登记公钥,每一个域名在自己的上级登记,然后别人在解析的时候,在每一层都对这个公开的记录来进行验证。从而确保整个解析链路都是完整且没有被破坏的。
unbound 就是发挥这个解析功能,支持 DNSSEC 的 DNS-resolver。安装后,你本地的域名解析就可以确保是安全的,然后 mox 就需要 unbound 来确保这层安全性。
how - 安装和调试
直接sudo apt install unbound
就可以下载安装unbound
,接下来就是调试,并配置相关设置。
配置方面有两个需要完成的点:
- 设置 root.key,来确保 DNSSEC 运行的时候有私钥可以用
- 如果是 VPS,通常会被供应商提前设置相应的 DNS resolver => 需要设置成本地的 unbound
unbound 的官方文档给的设置说明很详细:https://unbound.docs.nlnetlabs.nl/en/latest/getting-started/configuration.html#
我改动的主要是/etc/unbound/unbound.conf
:
server:
use-syslog: no
root-hints: root.hints
chroot: ""
username: ""
interface: 127.0.0.1
第二个点可能需要用resolvconf
来搞定,不要手动改,直接运行 sudo resolvconf -u
– 会生成/etc/resolv.conf
, 在里面设置name_servers=127.0.0.1
即可。然后用sudo systemctl start unbound
启动,使之成为常驻 service。
如果一切顺利,可以用dig google.com
来测试下,是否本地的 DNS resolver 已经设置好:
dig google.com
; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16515
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 300 IN A 172.217.18.14
;; Query time: 32 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Fri Aug 08 14:59:24 CEST 2025
;; MSG SIZE rcvd: 55
可以看到倒数第三行的 server 已经是127.0.0.1
。
这时再用 mox 来验证一下,看两者是否已经匹配上,回到 mox 的文件夹,运行:
./mox dns lookup ns com.
ns records (13, with dnssec):
- &{b.gtld-servers.net.}
- &{j.gtld-servers.net.}
- &{f.gtld-servers.net.}
- &{g.gtld-servers.net.}
- &{m.gtld-servers.net.}
- &{c.gtld-servers.net.}
- &{i.gtld-servers.net.}
- &{a.gtld-servers.net.}
- &{l.gtld-servers.net.}
这里 mox 就模拟了下 DNS 查询,你可以看到记录里有with dnssec
的表示,这就说明 DNSSEC 已经配置完成,unbound 安装结束。
到这里大部分的配置都已经完成,我们可以试着启动下 mox:
sudo ./mox quickstart -existing-webserver -hostname mail.paomian.de peiran@paomian.de
Checking if DNS resolvers are DNSSEC-verifying... OK
Looking up IPs for hostname mail.paomian.de... OK
Looking up reverse names for IP(s) 85.209.49.130...
WARNING: expected exactly 1 name for 85.209.49.130, got 2
...
Checking if outgoing smtp connections can be made by connecting to gmail.com mx on port 25... OK
Checking whether host name IPs are listed in popular DNS block lists... OK
creating file "config/adminpasswd": open config/adminpasswd: file exists
这里可以看到基本配置都弄好了,接下来可以启动 mox sudo systemctl start mox
,这样就可以使用 mox 的管理员页面,方便后面的 DNS records 设置。
在启动 mox 的时候,如果发生 bind issues 报错,比如:
l=fatal m="http: listen" err="listen tcp4 172.31.0.1:81: bind: cannot assign requested address" pkg=http addr=172.31.0.1:81
说明你的服务器那个addr后面的地址已经被其他内部服务给占了,不支持你绑定它,只需要进入/home/mox/config/mox.conf
文件,找到Listeners: internal
下面列出的几个内部 IP 地址,然后删除掉出现错误的那个就好。
配置 DNS records
到这里如果一切顺利,mox 已经在后台运行,但是距离发邮件还有点儿距离,需要配置一些 DNS records,这些记录帮助我们在公共空间声明我们邮件服务器的“正统性”。
找到需要的 records
这些记录在你第一次mox quickstart xxx
的时候,应该也会有相应提示,也可以用那个来直接配置,但是一旦你没有保存,那么这个就讲一下如何再度获取。可以用 ssh 来打开一条我们本地机器到服务器的隧道,方便我们在本地的浏览器上使用 mox 的 web interface。以此来获得需要配置的 DNS records。
刚才在配置 mox 的时候提到过AdminHTTP Port: xxx
的设置,我们目标就是嫁接一个本地的端口到这个端口 xxx 的隧道:
# 假如
# AdminHTTP 的 port: xxx 是1080,
# 你的服务器地址是 server1.com
# 你登录服务器的用户名是 accountYou
# 你希望本地用的端口是 8080
ssh -L 8080:localhost:1080 accountYou@server1.com
这样在本地用浏览器打开localhost:8080/admin
就可以直接进入mox的管理员页面了。现在在Domains
下面找到你配置的 domain,点进去:
第一个选项:Required DNS records 就是需要的记录。
第二个选项也很有用,它总结了目前所有的配置是否有问题。点进去会看到 mox 需要的不同的配置,比如 DNSSEC,MX,或者 DKIM 设置等。每个配置还会有一个Show instruction
的选项,点开就是相应配置的说明。比如下面就是我截取的关于 SPF 设置的说明:
配置 records
这里就需要你的域名服务商了,你可以用域名商+DNS records
来作为关键字搜索,看如何配置你的 records,大的域名服务会给你提供图形界面,也会有 API 提供使用。
我用的 netcup,虽然也有图形界面,但是非常不好用,而且在配置一个关键 records 来设置你的公共密钥时,因为密钥特别长,所以在图形界面里根本无法提交,总是报错。我只能找到 netcup 的相应 API 来使用。
还有点需要注意的是长的 record,可能需要特殊处理,具体取决于你用的方法和服务商的设置。比如 mox 提示我设置下面的公钥 records:
2025b._domainkey.paomian.de. TXT (
"v=DKIM1;h=sha256;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8wsFKsKSy+V4pcoXX5cSEG8n4MBY3qMsw2Yk3"
"naLsLvHS2mpvyOb2NW3iYmtd/DPA5hQI8zFSpj2DQG3vFKJ+ecvU64ai7S6Mfij88Vp+RMNSXXKXF0FyHTejwepq3POxEE+g0YF1"
"4+3oX6WhbPKczj3BlrQj4wdJI6JviNNl3wnQJbcIfBqCNg+bQ8rc6h1azL6kVkdZKDBKdaVffpxZjs1A9RSRyOmGCHDZkiiExZMS"
"CwhMlug5rwX17Nz5L2Q7AmxAwabF7bTbm4UDJpk8dHGGuMOxTnhn+9/2gNJ0yASGLe7A+y5/nVYEHYIkk+n8iYIV7B6cETvaPsA0"
"4BJfQIDAQAB"
)
注意在 TXT 里面的分段信息,每个都用"
包裹着,而下面是我用 API 直接更新时的 JSON 字段:
{
hostname: '2025d._domainkey.paomian.de.',
type: 'TXT',
destination: 'v=DKIM1;h=sha256;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAofS5rR6CxH2D48Ed37U9m+0y9CCa9OosBkVRZUsK/Esc0QT5VQwLo7gHPjvvuTZ5ony16QTYkX/szD3Fh9CbyJXFWZMYDeH99TmD42uRQgbouEg4Qw2L9HDzBhw235h02ON5uKlr/gZ4Yw1SpcC2yYeoJNc6j/iFRhaY4yEyLQ0GhGT82GoVmI/voKh/17S0eFN+pSqX8CtvAoxvY0YNMdFuorA0raimxrDsKRq4/zYgE5PnDk7vNIChyKPgze19EPxkMVE1VsHhVlHOztddXZsA2mHj/h/bd5GYoGlVmmeMtbuRI8loyDLHHYfzfCknz4zD1EfjJrZQhBS4vTFD6wIDAQAB',
},
这里分段是不被 API 接受的,需要自己整理成一个完整的 String。
如果使用 API,还可以在 github 上用域名服务商作为关键词搜索一下,有很多人有相同的问题,会写好相应的请求包,你只需要调取使用就好。我就是用的netcup-node
,来更新我的 DNS records。
配置 proxy
长征三万里,快结束了~ 这里如果一切顺利,点进前面 admin 页面里的 dns check,应该是一片绿色的 ok 了。现在我们需要完成最后一块拼图,配置下 proxy。
这里因为是安装 mox 在已有的域名之后,所以没有让 mox 自己监听 TLS/SSL 的端口443,而是前面放了一个 nginx 来接收一切。在前面的更改 mox 配置
下面提到了autoconfiguration/autodiscovery
和MTASTSHTTPS
这两项的port
设置,我们就是要重新导流,把 nginx 接收到的特殊的请求转移到这两个port
里面。
请看/etc/nginx/sites-enabled/default
的设置:
# mox mail server
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate ${pathToFullChain}/fullchain.pem;
ssl_certificate_key ${pathToKey}/key.pem;
server_name mta-sts.paomian.de;
location / {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:81;
proxy_redirect off;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /home/www-data/certs/paomian.de/fullchain.pem;
ssl_certificate_key /home/www-data/certs/paomian.de/key.pem;
server_name autoconfig.paomian.de;
location / {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:81;
proxy_redirect off;
}
}
设置完记得重启 nginx,大功告成✅。
现在就可以用自己的域名愉快的收发邮件了!还可以给自己开多个邮件账户,分别针对不同的应用,看到邮件嗖嗖发出去~ 快感拉满!
调试总结
- 多查看 mox 官方指令集,里面有一些很实用的命令,比如
mox config test
,mox dns lookup
,结合解释来明确自己哪里还没有配置好。 - 多用
sudo systemctl start mox.service
来启动 mox,然后sudo systemctl status mox.service
来查看情况 - 多用
sudo journalctl -t mox -b0 -r
来查看 mox 的 logs。 - 多用 admin webmail 来检查设置。在运行开 mox 后,进入 admin 页面就有很多可以浏览调试的地方,并且有解释。
- mox 的文件夹只能用 root 权限打开,多用
su -
切换到 root。 - 熟练掌握 vim,才能在服务器端配置的风生水起。