Discourse 续订证书失败

继续从这里对话:

这是我第一次收到 Redsift 的提醒,说我的证书将在一周内过期。通常 Discourse 会提前很久更新证书。这次没有,在我开始重建(这应该能解决问题)之前,@Falco 你有什么想让我检查并在这里回复的,以帮助找到证书未更新的根本原因吗?

根证书是 ISRGX1,这是即将过期的证书信息:

通用名称 (CN) E6
组织 (O) Let’s Encrypt
组织单位 (OU) 证书不包含此项
签发日期 2025年7月16日星期三下午7:36:45
到期日期 2025年10月14日星期二下午7:36:44

当前构建版本是 3.6.0.beta1-dev (7ee52c8f85)

1 个赞

Let’s Encrypt 所需的端点曾有一段时间被重定向。如果重建,该问题已修复。

5 个赞

更新后多久应续订证书?

如果记忆没错的话,证书有效期为 3 个月,现在他们将在到期前尝试自动续订。

1 个赞

我知道它是如何运作的。

但距离我更新论坛软件已经过去一天多了,证书似乎还没有更新。它还有 5 天到期,所以真的需要尽快续订。

我使用的是 Discourse 稳定分支,如果这有区别的话。修复端点是否有可能没有被移植?

对我来说,证书在重建后立即更新了

您是通过网络还是命令行重新构建的?

1 个赞

是的,解释在这里:

1 个赞

我的论坛在我执行命令行重建后终于更新了证书。

3 个赞

我们也有同样的 SSL 未续订的经历。

如果有人能仔细检查一下 discourse-docker 上的 web.ssl.template 是否正常工作,那就太好了。在我看来,端口 80 实际上并没有提供 Let’s Encrypt 使用的任何 /.well-known/ URL,所有 URL 都被重定向到 SSL,包括我手动放入 /var/www/discourse/public/.well-known/ 中的测试文件。我不得不直接在应用程序容器中编辑 /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf。

也许这发生在 discourse-docker 的提交 ae4887a 之后?

1 个赞

最近一次出现臭名昭著的路线错误是什么时候?

你上次进行重建是什么时候?

1 个赞

我也是。我没有收到关于证书过期的警告。进入服务器并执行重建 /var/discourse % ./launcher rebuild 解决了问题。

2 个赞

在我的测试中,使用 vanilla nginx 安装(1.18.0,但我认为 1.26.3 也是如此),nginx 配置行 return 301 https://thehostname$request_uri; 在 location 块之外会完全覆盖它之前的任何 location 块,而不是作为捕获所有。我相信 /.well-known/ 仅在端口 80 上提供服务,除非 301 重定向专门用于服务器块末尾的 / 等其他 location。这会不会是 这个 stackoverflow 帖子 的同一个问题?

很高兴 rebuild 能正常工作,但由于证书已经为我续订,我无法确认 rebuild 是否能在证书过期的情况下让 Let’s Encrypt 的验证服务器到达。也许 rebuild 会在模板行就位之前启动证书续订,或者类似的原因,而不是修复模板,但我无法确认 rebuild 为什么能成功续订。

如果您认为这是一个 Discourse,那么您应该在 github commit 上回复或打开一个新的大报告。

1 个赞

我可以确认 letsencrypt 续订失败了。我已经自托管 Discourse 很多年了,非常奇怪的是,在过去几个月里,我的续订连续两次失败。第二次是今天早上,所以我开始调查。

我追踪到了以下两个提交:

以及相关的链接行:

我认为有两个问题。

首先,return 301 https://${DISCOURSE_HOSTNAME}$request_uri; 会变成 return 301 https://<我的服务器名称> 而末尾没有 $request_uri。我在我的自托管安装以及一位朋友上周设置的自托管安装上都验证了这一点。我不明白 Discourse 模板是如何工作的,所以不知道为什么它会被删除。

其次,正如 @lessLost 所提到的,301 重定向位于 location 块之外。我认为服务器级别的重定向会覆盖所有 location 块。LetsEncrypt 在续订时使用 http。然而,任何尝试 curl -I http://YOUR_DOMAIN/.well-known/acme-challenge/test 的操作都会返回 301 重定向到 https,而不是 404(这是预期的行为;我们想要 404 而不是 301)。

我已经在我自托管的安装上手动修复了这个问题,但我预计任何更新都会覆盖我的更改。不幸的是,我不够了解模板,无法提交一个 pull request 给 @pfaffman——否则我也会这么做。

编辑补充:

我认为这是错误的——

我相当确定 LetsEncrypt 默认使用 http(出于明显的原因,如果证书过期了,它就无法续订!),但将 301 放在服务器块级别会强制所有请求 301 重定向到 https,这与此续订策略不一致。

1 个赞

您上次重建是什么时候?

今天早上,在我醒来大约 10 分钟后,我访问了我的论坛,发现证书又过期了。(上次证书过期——大约 3 个月前——是通过重建来续期的?)

我认为他们在那之后已经提交了修复此问题的更改,但由于需要 3 个月才能知道结果,所以尚无定论。您可以在当前证书过期前几周设置一个提醒。

1 个赞

这不正确。

  1. 我在上面的评论中附加的链接来自 git blame。这是该文件的最新版本(相关行已链接):discourse_docker/templates/web.ssl.template.yml at 247c71a1e45d32b0b814a8e9d5fdaa4faaf727b9 · discourse/discourse_docker · GitHub
  2. 我朋友的新站点安装是在一周前。上述模板的第 37 行显示:return 301 https://${DISCOURSE_HOSTNAME}$request_uri; 但在 Discourse Docker 容器中,她(和我的)/etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf 显示为 return 301 https://\u003cour_discourse_site\u003e; 注意 $request_uri 是如何被移除的。肯定是什么东西导致它消失了!(我不知道是什么)。
  3. 今天早上,我作为调查的一部分进行了一次模拟的强制续订。它失败了。然后我修改了 /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf。它成功了!

这实际上没关系;我每次更新 Discourse 时都会手动编辑 20-redirect-http-to-https.conf。对于偶然看到此评论的人,要运行的命令是:

cat > /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf << 'EOF'
server {
  listen 80;
  listen [::]:80;

  location ~ /.well-known {
    root /var/www/discourse/public;
    allow all;
  }

  location / {
    return 301 https://\u003cYOUR_FORUM_ADDRESS\u003e$request_uri;
  }
}
EOF

我不太确定是什么导致了这次失败,但我知道修改上面的配置文件可以解决问题。但我还修改了通知设置,这样 letsencrypt 续订就不会再静默失败了——这样我就可以提前得到一些警告。只是想让你知道!

4 个赞

感谢您的报告,我认为这是真实的。

(抄送 @featheredtoast

6 个赞