CloudFlare 用例
这些说明适用于使用 Cloudflare 代理的自托管 Discourse 论坛。
当您使用 Cloudflare 代理时,这会阻止所有 SMTP(端口 25)流量到达您的服务器。这要求您为邮件接收器(mail-receiver)设置一个不同的子域名才能正常工作。
例如,如果您的域名是 forums.domain.tld,则需要创建一个新的子域名,例如 mail.domain.tld。
使用 Cloudflare 时,您需要执行以下附加步骤。
- 为新子域名创建 A 记录。它将使用与您的
forums.domain.tld 相同的 IP 地址。
- 按照主说明中提供的方式为新子域名创建 MX 记录。
遵循主要说明,只需进行此微小更改。在关闭 TLS 安全的情况下,它可以正常工作。
如果您想运行 TLS 安全,则需要进行额外的工作。
TLS 设置概述
这些说明将安装 Certbot 和一个 CloudFlare Certbot 插件。这些命令将通过 DNS 认证过程以独立模式(Standalone)获取 Let’s Encrypt 证书。一旦证书可用,它们将被复制到邮件接收器的共享区域供容器使用。我们必须使用 DNS 模型,因为 Discourse 已经占用了端口 80。
DNS 挑战
Certbot 不再通过 HTTP 证明域名所有权,而是通过在您的 DNS 中创建 TXT 记录来证明。由于您的 DNS 是 Cloudflare,这可以通过 Cloudflare API 令牌完全自动化——无需端口 80,无需关闭 Web 服务器。
工作原理
Certbot → 在 Cloudflare 中创建 _acme-challenge.mail.lotuselan.net TXT 记录
Let's Encrypt → 查找该 TXT 记录 → 验证 → 发布证书
Certbot → 删除 TXT 记录
所有这些都在您的基础服务器上完成,而不是在 discourse 容器内完成。
设置
1 — 安装 cerbot 和 Cloudflare certbot 插件:
bash
apt install certbot python3-certbot-dns-cloudflare -y
2 — 创建一个 Cloudflare API 令牌:
- 转到 Cloudflare → 我的个人资料 → API 令牌 → 创建令牌
- 使用 “编辑区域 DNS” 模板
- 权限:
区域 → DNS → 编辑
- 区域资源:
包括 → 特定区域 → lotuselan.net
- IP 限制:仅设置为允许来自您的服务器 IP 地址的访问
- 复制令牌
3 — 将令牌保存到凭据文件:
bash
mkdir -p /etc/letsencrypt/cloudflare
nano /etc/letsencrypt/cloudflare/credentials.ini
粘贴:
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
锁定文件:
bash
chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
4 — 请求证书:
使用您的管理员电子邮件和域名更新以下命令。
bash
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
--non-interactive \
--agree-tos \
--email youremailadress@domain.tld \
-d mail.domain.tld
在您的结果中,应该有一条说明,内容如下:
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Certbot 将设置一个 cron 任务,每天检查两次证书到期情况。如果证书在 30 天内到期,它将续订证书。您可以通过以下方式验证:
# 检查 systemd 计时器是否处于活动状态(大多数现代 Ubuntu 系统)
systemctl status certbot.timer
# 或检查是否添加了 cron 作业
cat /etc/cron.d/certbot
现在您的服务器上有了新邮件接收器域名的 TLS 证书。它们不在可以使用的位置。
5 — 设置部署脚本以移动文件
由于 certbot 会自动续订,您只需要脚本来处理 Discourse 特定的部分——复制已续订的证书并重建邮件接收器。您可以通过使用 certbot 内置的**部署挂钩(deploy hook)**来大大简化脚本,该挂钩在成功续订后自动运行。
创建一个部署挂钩文件:
bash
nano /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh
粘贴以下内容:
bash
#!/bin/bash
DOMAIN="mail.domain.tld"
DISCOURSE_DIR="/var/discourse"
CERT_SRC="/etc/letsencrypt/live/${DOMAIN}"
CERT_DEST_1="${DISCOURSE_DIR}/shared/mail-receiver/letsencrypt/${DOMAIN}"
CERT_DEST_2="${DISCOURSE_DIR}/shared/mail-receiver/letsencrypt/${DOMAIN}_ecc"
ADMIN_EMAIL="admin email address"
LOG_FILE="/var/log/mail-cert-renewal.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== Certbot deploy hook triggered for ${DOMAIN} ==="
# 复制证书(使用 -L 解析符号链接)
for DEST in "$CERT_DEST_1" "$CERT_DEST_2"; do
mkdir -p "$DEST"
cp -L "${CERT_SRC}/fullchain.pem" "${DEST}/fullchain.pem"
cp -L "${CERT_SRC}/privkey.pem" "${DEST}/privkey.pem"
cp -L "${CERT_SRC}/cert.pem" "${DEST}/cert.pem"
cp -L "${CERT_SRC}/chain.pem" "${DEST}/chain.pem"
chmod 644 "${DEST}/fullchain.pem" "${DEST}/cert.pem" "${DEST}/chain.pem"
chmod 600 "${DEST}/privkey.pem"
log "Certs copied to ${DEST}"
done
# 重建邮件接收器
cd "$DISCOURSE_DIR" || { echo "Cannot cd to ${DISCOURSE_DIR}" | mail -s "[FAILURE] Mail cert deploy hook failed" "$ADMIN_EMAIL"; exit 1; }
log "Rebuilding mail-receiver..."
if ./launcher rebuild mail-receiver >> "$LOG_FILE" 2>&1; then
log "mail-receiver rebuilt successfully"
else
log "ERROR: rebuild failed"
echo "mail-receiver rebuild failed after cert renewal. Check ${LOG_FILE}" | \
mail -s "[FAILURE] Mail cert deploy hook failed" "$ADMIN_EMAIL"
exit 1
fi
log "=== Deploy hook completed successfully ==="
完全不需要手动设置 cron 任务——certbot 会协调整个过程。部署挂钩仅在实际发生续订时触发,因此在 certbot 检查但未续订的日子里,您的邮件接收器不会不必要地重建。
要测试续订挂钩,请运行以下命令:
bash
bash /etc/letsencrypt/renewal-hooks/deploy/mail-receiver-deploy.sh
如果一切设置正确,它将
→ 将证书复制到 Discourse 目录
→ 重建邮件接收器
→ 记录所有内容
6 — 在 mail-receiver.yml 中设置 TLS