前言:
Poste.io 是一个运行在 Docker 中的完整邮件服务器项目,集成了 SMTP、IMAP、POP3、反垃圾邮件、病毒扫描、Webmail(Roundcube)和网页管理面板。
本文使用 Poste.io 的免费镜像
analogic/poste.io,在 VPS 上搭建一个可用自己的域名收发邮件的邮局,例如[email protected]。
它和普通博客、面板项目不一样:邮件服务是否能正常投递,关键不只在容器能否启动,还取决于 25 端口、PTR 反向解析、MX、SPF、DKIM、DMARC 是否完整。 少其中一项,轻则邮件进垃圾箱,重则无法向外发信。
Poste.io 官网:https://poste.io/
官方部署文档:https://poste.io/doc/getting-started
我的博客:rckin.com
一、前置准备
1.1、准备一台 VPS
建议使用一台独立 IPv4 的海外 VPS,Ubuntu 22.04 / 24.04 均可。
最低建议配置:
| 项目 | 建议 |
|---|---|
| 内存 | 2G 起步,推荐 4G |
| 硬盘 | 20G 起步,邮件会持续占用磁盘 |
| IP | 独立公网 IPv4,最好同时有 IPv6 |
| 系统 | Ubuntu 22.04 / 24.04 64 位 |
重要: 很多 VPS 厂商默认封禁 SMTP 的 25 端口,尤其是新开通的机器。购买前先问客服是否允许 25 端口出站和入站;如果 25 端口被封,Poste.io 仍可登录网页邮箱,但无法正常和其他邮件服务器收发邮件。
1.2、准备一个域名
本文以 example.com 为例,邮件服务器主机名使用:
mail.example.com
邮箱地址则可以是:
[email protected]
[email protected]
域名需要可以自行管理 DNS 记录,推荐托管到 Cloudflare 或域名注册商自己的 DNS 面板。
注意:
mail.example.com这条 A 记录在 Cloudflare 中必须关闭橙色云朵代理,保持为 DNS only(仅 DNS)。Cloudflare 普通代理不转发 SMTP、IMAP 等邮件端口。
1.3、确认 VPS 允许修改 PTR 反向解析
PTR(反向 DNS)是把服务器 IP 反查回主机名的记录。请到 VPS 控制台设置,或者让客服把你的服务器 IP 的 PTR 修改为:
mail.example.com
如果 VPS 商家不支持修改 PTR,不建议继续把它作为正式邮件服务器使用。Gmail、Outlook 等服务会明显降低这类邮件的可信度。
1.4、下载 SSH 连接工具
法 1:官网下载 MobaXterm
法 2:使用自己熟悉的 Windows Terminal、Termius 或 Xshell。
使用 SSH 连接进入 VPS 后,就可以开始部署。
二、更新工具
直接从这里开始输入代码就行。
2.1、切换到 root 用户
sudo -i
2.2、更新软件包索引
apt update -y
2.3、安装常用工具
apt install -y wget curl sudo vim git ca-certificates
这些工具用于:
| 工具 | 作用 |
|---|---|
| wget / curl | 下载文件、测试网络 |
| vim | 编辑配置文件 |
| git | 下载项目源码时使用 |
| ca-certificates | 验证 HTTPS 证书 |
三、安装 Docker 环境(非大陆 VPS)
已经安装 Docker 和 Docker Compose 的小伙伴,可以直接跳到第四步。
3.1、安装 Docker
curl -fsSL https://get.docker.com | bash
3.2、查看 Docker 版本
docker -v
如果出现类似:
Docker version 2x.xx
说明安装成功。
3.3、设置 Docker 开机自启
systemctl enable --now docker
3.4、安装 Compose 插件
apt install -y docker-compose-plugin
3.5、查看 Compose 版本
docker compose version
四、部署 Poste.io 邮件服务器
4.1、先确认端口没有被其他项目占用
Poste.io 使用宿主机网络模式,需要直接占用 25、80、443、465、587、993 等端口。因此,如果你已经部署了 Nginx Proxy Manager、宝塔、Caddy、Halo 等占用了 80/443 的项目,不能直接照本文部署。
先执行:
ss -lntp | grep -E ':(25|80|110|143|443|465|587|993|995|4190)\b'
没有输出才表示这些端口暂未被占用。
不要把 Poste.io 当成普通网站只映射一个
8080端口再交给 Nginx 反代。这样网页虽然可能能打开,但 SMTP、IMAP、自动签发证书和客户端收发邮件都会出现问题。官方推荐使用--network host。
4.2、创建数据目录
mkdir -p /root/data/docker_data/poste-io/data
目录结构:
/root
└─ data
└─ docker_data
└─ poste-io
├─ docker-compose.yml # 容器配置
└─ data # 邮件、账号、证书、日志和配置
重要:
data目录就是整个邮件服务器的核心数据。备份、迁移、升级前,都应先备份它;不要随意删除。
4.3、进入项目目录
cd /root/data/docker_data/poste-io
4.4、创建 docker-compose.yml
nano docker-compose.yml
输入以下内容,把其中的 mail.example.com 改为你自己的邮件服务器域名:
services:
poste-io:
image: analogic/poste.io:latest
container_name: poste-io
hostname: mail.example.com
network_mode: host
restart: unless-stopped
environment:
TZ: Asia/Shanghai
volumes:
- ./data:/data
保存按 Ctrl + O,再按 Enter 确认;退出按 Ctrl + X。
配置说明
| 配置 | 作用 |
|---|---|
hostname |
邮件服务器名称,必须与 mail.example.com的 A、PTR 记录一致 |
network_mode: host |
让容器直接使用 VPS 网络,确保真实客户端 IP、IPv6 和全部邮件端口正常工作 |
./data:/data |
将重要数据保存在宿主机,删除容器也不会丢失邮件 |
restart: unless-stopped |
服务器重启后自动拉起容器 |
TZ |
设置邮件时间为上海时区 |
本文使用官方免费镜像的
latest标签,方便新手安装。正式长期使用前,建议你在确认运行稳定后记录当前镜像摘要;升级时先备份数据、在维护窗口验证,而不是不加检查地更新。
4.5、此时先不要启动容器
docker-compose.yml 保存完成后,先不要执行 docker compose up -d。
Poste.io 的主机名、DNS 和 TLS 证书相互关联。下一章先完成以下条件:
mail.example.com已解析到这台 VPS 的公网 IP;- Cloudflare 代理已关闭,记录为 DNS only(仅 DNS);
- VPS 和云厂商防火墙已允许 80、443 等端口;
- 服务器 IP 的 PTR 已设置为
mail.example.com。
这些条件确认无误后再启动容器。需要区分:A 记录正确并且 80 端口公网可达,是 Let's Encrypt HTTP-01 验证的前提;PTR 不参与证书签发,但会影响后续邮件投递信誉,因此本文把它也列入启动前检查。
五、先配置服务器域名和防火墙,再启动 Poste.io
本章顺序不要打乱:先配置
mail.example.com的 A 记录和服务器 PTR,再核对公共 DNS、放行端口、启动容器,最后只通过正式域名进入初始化页面。本文不使用 VPS IP 作为临时登录地址。
5.1、添加邮件服务器的 A 记录
进入域名的 DNS 管理面板,添加:
| 类型 | 名称 | 内容 | 代理状态 |
|---|---|---|---|
| A | mail |
你的 VPS 公网 IPv4 | DNS only(仅 DNS) |
例如 VPS IPv4 是 203.0.113.10,域名是 example.com,最终关系应为:
mail.example.com → 203.0.113.10
如果域名托管在 Cloudflare,必须关闭 mail 记录的橙色云朵。Cloudflare 普通代理不转发 SMTP、IMAP、POP3;开启代理后,mail.example.com 还会解析到 Cloudflare 的代理 IP,而不是你的邮件服务器 IP。
暂时不要添加 AAAA 记录
新手建议先只使用 IPv4。只有下面条件全部满足时才添加 AAAA:
- VPS 确实分配了可公网访问的 IPv6;
- IPv6 路由和服务器防火墙已正确配置;
- 外部网络可以通过该 IPv6 访问 80、443 和所需邮件端口;
- 你可以为该 IPv6 设置正确的反向解析。
错误或不可达的 AAAA 记录可能导致 Let's Encrypt 和客户端优先连接失败。Poste.io 官方也建议:不熟悉 IPv6 时不要贸然启用。
5.2、设置 PTR 反向解析
PTR 不是在 Cloudflare 的普通 DNS 页面添加,而是在 VPS 服务商控制面板设置。找不到入口就提交工单,请商家把 VPS 公网 IPv4 的 PTR 设置为:
mail.example.com
正确的正向和反向关系应当一致:
mail.example.com --A记录--> VPS公网IPv4
VPS公网IPv4 --PTR记录--> mail.example.com
PTR 不一致通常不会阻止网页后台打开,但会影响邮件服务器信誉和外发邮件接受率,因此正式发信前必须处理。
5.3、检查公共 DNS 是否已经生效
安装 DNS 查询工具:
apt install -y dnsutils
查询 A 记录:
dig +short A mail.example.com @1.1.1.1
输出必须是你的 VPS 公网 IPv4。
查询 PTR 时,把示例 IP 换成自己的 VPS 公网 IPv4:
dig +short -x 203.0.113.10 @1.1.1.1
输出应为:
mail.example.com.
如果配置了 AAAA,还必须检查:
dig +short AAAA mail.example.com @1.1.1.1
不要只使用 ping 判断 DNS。ping 可能受本机缓存、IPv6 优先级和 ICMP 防火墙影响,不能完整证明公共 DNS 配置正确。
A 记录还没有返回 VPS IP 时,不要启动 Poste.io,也不要继续访问初始化页面。等待解析传播完成,或回到 DNS 面板检查名称、IP 和代理状态。
5.4、放行服务器端口
Poste.io 官方列出的端口如下:
| 端口 | 用途 | 本文处理方式 |
|---|---|---|
| 25 | 邮件服务器之间的 SMTP 收发 | 必须允许入站和出站 |
| 80 | HTTP 跳转、Let's Encrypt HTTP-01 验证 | 必须开放 |
| 443 | 管理后台和 Webmail 的 HTTPS | 必须开放 |
| 465 | 邮件客户端 SMTPS 发信 | 开放 |
| 587 | 邮件客户端 Submission(STARTTLS)发信 | 开放 |
| 993 | IMAPS 加密收信 | 开放 |
| 995 | POP3S 加密收信 | 使用 POP3 时开放 |
| 110 / 143 | POP3 / IMAP 的 STARTTLS 入口 | 使用相应协议时开放 |
| 4190 | 远程管理 Sieve 过滤规则 | 按需开放 |
如果使用 UFW,先放行 SSH,避免启用防火墙后断开当前连接。下面假设 SSH 使用默认的 22 端口;修改过 SSH 端口的人必须把第一行换成自己的实际端口:
ufw allow 22/tcp
ufw allow 25/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 465/tcp
ufw allow 587/tcp
ufw allow 993/tcp
ufw enable
ufw status numbered
需要 POP3、IMAP STARTTLS 或远程 Sieve 时,再按实际需求放行 110、143、995、4190:
ufw allow 110/tcp
ufw allow 143/tcp
ufw allow 995/tcp
ufw allow 4190/tcp
还要登录 VPS 厂商控制台,在安全组/云防火墙中放行相同端口。UFW 和厂商安全组是两层独立防火墙,只配置其中一层不够。
UFW 默认策略通常允许出站连接;可用 ufw status verbose 检查。如果你主动设置过“拒绝全部出站”,还要执行 ufw allow out 25/tcp。此外必须确认服务商没有在平台层封禁 25 端口出站,这种限制无法用 UFW 解除,只能在厂商面板申请解封或联系客服。
5.5、正式启动 Poste.io
确认 5.1~5.4 均完成后,执行:
cd /root/data/docker_data/poste-io
docker compose up -d
查看容器状态:
docker compose ps
查看最近 200 行启动日志:
docker compose logs --tail=200
确认核心端口实际处于监听状态:
ss -lntp | grep -E ':(25|80|443|465|587|993)\b'
容器应显示为 Up,核心端口也应处于监听状态。若容器反复重启或 80/443 没有监听,先根据日志排错,不要进入下一步。
5.6、首次进入初始化页面
只能使用前面已经验证过的正式主机名:
https://mail.example.com/admin/
不要使用 https://VPS_IP 初始化。TLS 证书应签发给 mail.example.com,通过 IP 访问一定不能验证正式域名的 DNS、SNI 和证书链路是否正确。
首次访问出现证书警告怎么办
在正式 Let's Encrypt 证书尚未签发前,首次访问可能看到自签名证书或名称不匹配警告。这只能说明当前 443 端口提供的证书尚未受到浏览器信任,不能把它当成“部署成功”的结果。
继续初始化前,至少重新确认:
- 浏览器地址栏确实是
https://mail.example.com/admin/,不是陌生域名或直接 IP; dig +short A mail.example.com @1.1.1.1返回自己的 VPS IP;- Cloudflare 中的
mail记录为 DNS only; - 80/443 端口由这台 VPS 上的 Poste.io 提供,没有被其他网站或容器占用。
只有确认访问目标确实是自己的服务器后,才可以把这次不受信任证书作为初始化阶段的临时情况处理。完成下一节的 Let's Encrypt 配置后,必须重新验证证书;不能长期忽略警告,也不能在无法确认服务器身份时输入管理员密码。
创建首个系统管理员
首次安装需要创建系统管理员,并建立默认邮件域 example.com。管理员邮箱可以规划为:
[email protected]
管理员密码建议至少 16 位,包含大小写字母、数字和符号,并与普通邮箱密码分开。
【待实测补充】Poste.io 官方公开文档没有逐项列出当前免费版初始化表单的字段名称和顺序。正式发布本文前,请使用全新的
data目录实测一次,补充首次页面截图、实际字段、按钮名称和跳转结果。现在不编造“第一个填什么、第二个填什么”的页面步骤。能够确认的是:初始化完成后,Virtual domains中应已经出现默认邮件域example.com,不要再重复创建同名域。
5.7、签发并检查 Let's Encrypt 证书
Poste.io 官方当前演示后台中的证书入口为:
System settings → TLS certificate → Change certificate settings
基础配置只使用一个经过验证的主机名:
| 配置项 | 填写内容 |
|---|---|
| Enabled | 开启 |
| Common name | mail.example.com |
| Alternative names | 暂时留空 |
保存后等待页面中的证书申请日志返回成功。Poste.io 使用 Let's Encrypt,HTTP-01 验证需要公网能够通过 80 端口访问这台服务器。
不要随意把 smtp.example.com、imap.example.com 填入 Alternative names。每一个备用名称都必须先有正确 DNS 记录、指向本机并能从公网访问,否则可能导致整次证书申请失败。本文的客户端统一使用 mail.example.com,不需要备用名称。
签发完成后,关闭并重新打开:
https://mail.example.com/admin/
浏览器不应再显示证书警告。也可在 VPS 上检查证书颁发者、有效期和域名:
echo | openssl s_client -connect mail.example.com:443 -servername mail.example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
如果签发失败,依次检查:
- A 记录是否仍指向本机;
- 是否残留一个不可达的 AAAA 记录;
- 80 端口是否允许公网访问;
- Cloudflare 是否误开代理;
- 其他反向代理是否截获了
/.well-known/; - 容器日志是否出现 ACME 或证书错误。
筛选日志:
docker compose logs --tail=300 | grep -Ei 'letsencrypt|acme|certificate|cert|error'
【待实测补图】上面的菜单名称来自 Poste.io 当前官方演示后台。正式发布前仍应在本文实际使用的免费镜像版本中核对一次,并补上“开启 Enabled、填写 Common name、保存、申请成功”的连续截图。
5.8、添加 MX、SPF、DKIM、DMARC
Poste.io 已经启动、后台能够登录并且 HTTPS 证书正常后,再把根域名的收信流量切换到新服务器。
重要: 本节假设
example.com没有正在使用其他邮箱服务。如果当前使用腾讯企业邮、Google Workspace、Microsoft 365、Cloudflare Email Routing 等服务,直接替换 MX 会中断原服务。迁移场景必须另行设计,不能照抄本节。
5.8.1、添加 MX
在 DNS 面板添加:
| 类型 | 名称 | 内容 | 优先级 |
|---|---|---|---|
| MX | @ |
mail.example.com |
10 |
MX 的目标必须是主机名,不能填写 IP、https:// URL 或带端口的地址。优先级 10 是单台邮件服务器常用写法,不是 Poste.io 强制值。
5.8.2、生成并添加 DKIM
进入管理后台:
Virtual domains(虚拟域名) → example.com → Show
点击 create a new key 生成此域名的 DKIM,然后进入该域名的 DNS diagnostics。将页面给出的 DKIM 主机名和 TXT 内容完整复制到 DNS 面板。
DKIM 不能照抄文章、其他服务器或网上示例。 选择器和公钥由你的 Poste.io 实例生成,必须以自己的后台为准。DNS 面板只要求填写相对主机名时,是否保留末尾的
example.com也要按该 DNS 服务商的规则处理,避免域名被重复拼接。
5.8.3、添加 SPF
对于“所有外发邮件都由这台 MX 服务器发出”的简单场景,可添加:
| 类型 | 名称 | 内容 |
|---|---|---|
| TXT | @ |
v=spf1 mx ~all |
同一个域名只能有一条 SPF 记录。如果已经使用网站服务器、邮件营销平台或第三方 SMTP 发信,必须把多个来源合并到同一条 SPF 中,不能再单独创建第二条 v=spf1。
另外,v=spf1 mx ~all 只适用于外发 IP 与 MX 指向服务器一致的简单部署。如果 Poste.io 通过 smarthost 中继发信,或入站、出站 IP 不同,应按实际发信来源改写,不能照抄。
5.8.4、先添加监控模式 DMARC
初次部署可先使用不带报告地址的最小监控策略:
| 类型 | 名称 | 内容 |
|---|---|---|
| TXT | _dmarc |
v=DMARC1; p=none |
p=none 只用于观察验证结果,不要求收件服务器隔离或拒绝邮件。等下一章创建 [email protected] 邮箱或有效别名后,可改为:
v=DMARC1; p=none; rua=mailto:[email protected]
确认 SPF、DKIM 长期稳定通过并看懂 DMARC 报告后,再考虑 p=quarantine 或 p=reject。不要一开始就使用拒绝策略。
5.9、分别检查服务器 DNS 和邮件域 DNS
Poste.io 后台有两类诊断:
Server status → DNS diagnostics
Virtual domains → example.com → Show → DNS diagnostics
第一处主要检查邮件服务器主机名、A、PTR 和端口;第二处检查邮件域的 MX、SPF、DKIM、DMARC。两类诊断不是同一回事,不能只看其中一页。
DNS 刚修改时可能仍显示缓存结果。等待公共 DNS 更新后刷新诊断,确认所有与本文部署相关的项目都通过,再进入下一章创建普通邮箱并测试投递。
六、创建邮箱与收发测试
6.1、创建普通邮箱
在 Poste.io 管理面板进入:
Email accounts → Create new email account
例如创建:
[email protected]
设置独立的高强度密码。不要把管理员账号密码和普通邮箱密码设置成同一个。
如果准备接收 DMARC 汇总报告,再创建邮箱或别名:
[email protected]
确认这个地址能收信后,才把上一章的 DMARC 记录更新为带 rua=mailto:[email protected] 的版本。
6.2、登录网页邮箱
访问:
https://mail.example.com/webmail
使用刚创建的邮箱账号登录即可。Poste.io 内置的是 Roundcube Webmail。
6.3、邮件客户端参数
如需在 Outlook、Thunderbird、手机邮箱 App 中登录,可手动填写:
| 项目 | 参数 |
|---|---|
| 收件服务器 | mail.example.com |
| IMAP 端口 | 993,SSL/TLS |
| 发件服务器 | mail.example.com |
| SMTP 端口 | 587,STARTTLS;或 465,SSL/TLS |
| 用户名 | 完整邮箱地址,如 [email protected] |
| 密码 | 该邮箱自己的密码 |
不要使用明文认证,也不要为了兼容老旧客户端而关闭 TLS。邮件密码和邮件正文会经过公网传输,TLS 是基本要求。
6.4、测试投递
建议至少做两组测试:
- 用自己的邮箱向 Gmail / Outlook 发送一封测试邮件,检查是否进入收件箱;
- 用 Gmail / Outlook 回复这封邮件,检查 Poste.io 是否能正常收到。
如果邮件进入垃圾箱,首先回到 Poste.io 的 DNS diagnostics 检查 PTR、MX、SPF、DKIM、DMARC;其次确认 VPS IP 没有进入黑名单,以及 25 端口没有被商家限制。
七、备份、更新与常见问题
7.1、备份邮件数据
所有用户、邮件、证书和配置都在 data 目录中。建议定期备份到 VPS 之外的地方:
cd /root/data/docker_data/poste-io
tar -czf poste-io-data-$(date +%F).tar.gz data
会生成一个按日期命名的压缩备份文件。建议再下载到本地电脑或同步到另一台可靠的存储设备。
7.2、更新前先备份
不要直接更新正式运行中的邮件服务器。建议按下面顺序操作:
cd /root/data/docker_data/poste-io
docker compose down
tar -czf poste-io-data-before-update-$(date +%F).tar.gz data
docker compose pull
docker compose up -d
docker compose logs -f
确认日志和收发邮件都正常后,再按 Ctrl + C 退出日志查看。
更新期间邮件服务会短暂不可用,请选择低峰期操作。官方也明确建议升级前备份
/data目录。
7.3、查看容器状态
cd /root/data/docker_data/poste-io
docker compose ps
7.4、查看实时日志
cd /root/data/docker_data/poste-io
docker compose logs -f --tail=200
7.5、常见问题
① 网页能打开,但 Gmail 收不到邮件
优先检查:VPS 25 端口是否受限、MX 是否指向 mail.example.com、mail 的 A 记录是否正确。
② 发信总进垃圾箱
优先检查:PTR 是否为 mail.example.com、SPF/DKIM/DMARC 是否都通过、服务器 IP 是否有黑名单历史。
③ 访问不了 https://mail.example.com
检查 80/443 是否被其他容器或 Nginx 占用,确认 Cloudflare 的 mail 记录是否关闭代理,并等待 DNS 生效。
④ Docker 重启后邮件服务器没起来
执行:
systemctl enable --now docker
cd /root/data/docker_data/poste-io
docker compose up -d
八、相关文档
Poste.io 官网:https://poste.io/
Poste.io 官方快速开始:https://poste.io/doc/getting-started
Poste.io 官方 DNS 配置说明:https://poste.io/doc/configuring-dns
Poste.io 官方网络模式说明:https://poste.io/doc/network-schemes
Poste.io 官方客户端配置:https://poste.io/doc/client-settings
Poste.io 官方 FAQ(80 端口与 /.well-known/):https://poste.io/doc/faq
Poste.io 官方升级说明:https://poste.io/doc/updating
Docker Hub 免费镜像:https://hub.docker.com/r/analogic/poste.io
Cloudflare 官方邮件 DNS 排错:https://developers.cloudflare.com/dns/troubleshooting/email-issues/
评论区