⚠ 无法通过主机名 metabolism.logophilia.eu 访问此计算机的 443 端口 ----

您好,我在初始化过程中看到标题中提到的错误(见下文),当时显示“ 端口 80 和 443 可供使用”。DNS 已配置,SSL 已设置,网站可从外部访问(请自行测试),下方附有 curl 输出(已截断),即从本机也可访问。我已无头绪,不知还缺少什么。感谢任何见解。

附注:AlmaLinux 10.2 - 6.12.0-211.7.4.el10_2.x86_64

# ./discourse-setup  
→ 正在检查安装向导镜像更新... 
→ 正在启动 Discourse 安装向导... 
 
 
 ___  _ 
|   \(_)___ __ ___ _  _ _ _ ___ ___ 
| |) | (_-< / _/ _ \ || | '_(-</ -_) 
|___/|_/__/\__\___/\_,_|_| /__/\___| 
                       安装向导 
 
 
→ 本向导将协助您配置 Discourse 安装。 
→ 随时可按 Ctrl+C 取消。 
 
── 系统检查 ── 
 
[1/5] 验证系统要求 
✓ 以 root 身份运行 
✓ Docker 可用 
✓ 内存:8GB,CPU:4 核心 
 
── 配置 ── 
 
[2/5] 准备配置 
✓ 端口 80 和 443 可供使用 
→ 正在创建新配置... 
→ 正在从模板创建新配置... 
 
── 站点设置 ── 
 
[3/5] 输入您的站点详情 
 
管理员账户的电子邮件地址? 
eduard.pech@logophilia.eu▌ 
 
您是否为 Discourse 准备了域名? 
▸ 是      否 
 
Discourse 的主机名? 
metabolism.logophilia.eu▌ 
 
是否配置 SMTP 以发送邮件?(需要 SMTP 凭据) 
  是    ▸ 否 
 
 
── 审查配置 ── 
 
 
╭────────────────────────────────────────────╮ 
│                                            │ 
│  主机名         metabolism.logophilia.eu   │ 
│  管理员邮箱     eduard.pech@logophilia.eu  │ 
│  SMTP           (未配置)                 │ 
│  Let's Encrypt  已启用                     │ 
│                                            │ 
╰────────────────────────────────────────────╯ 
 
 
这样看起来正确吗? 
▸ 是      否 
→ 检测到 8GB 内存和 4 个 CPU 核心 
→ 设置 db_shared_buffers = 2048MB 
→ 设置 UNICORN_WORKERS = 8 
 
── 网络验证 ── 
 
[4/5] 验证域名配置 
→ 正在检查您的域名... 
⚠ 此计算机的端口 443 似乎无法通过主机名 metabolism.logophilia.eu 访问 
⚠ 连接到 http://metabolism.logophilia.eu(端口 80)也失败。 
 
这表明 metabolism.logophilia.eu 解析到了某个无法到达您正在安装 Discourse 的这台机器的 IP 地址。 
 
首先要做的是确认 metabolism.logophilia.eu 是否解析到了本服务器的 IP 地址。 
您通常可以在购买域名的同一处进行此操作。 
 
如果您确定 IP 地址解析正确,则可能是防火墙问题。 
搜索“开放端口 您的云服务提供商”可能会有所帮助。 
 
本工具仅适用于最标准的安装。如果您无法解决上述问题,则需要自行编辑 containers/app.yml,然后输入: 
 
    ./launcher rebuild app 
 
 
✗ metabolism.logophilia.eu 的 DNS 验证失败 
[root@logophilia discourse]# dig metabolism.logophilia.eu 
 
; <<>> DiG 9.18.33 <<>> metabolism.logophilia.eu 
;; global options: +cmd 
;; Got answer: 
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36726 
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 
 
;; OPT PSEUDOSECTION: 
; EDNS: version: 0, flags:; udp: 512 
;; QUESTION SECTION: 
;metabolism.logophilia.eu.      IN      A 
 
;; ANSWER SECTION: 
metabolism.logophilia.eu. 300   IN      A       75.119.134.68 
 
;; Query time: 8 msec 
;; SERVER: 213.136.95.10#53(213.136.95.10) (UDP) 
;; WHEN: Sat Jun 06 04:52:23 CEST 2026 
;; MSG SIZE  rcvd: 69 
 
[root@logophilia discourse]# curl -v https://metabolism.logophilia.eu 
* Host metabolism.logophilia.eu:443 was resolved. 
* IPv6: (none) 
* IPv4: 75.119.134.68 
*   Trying 75.119.134.68:443... 
* ALPN: curl offers h2,http/1.1 
* TLSv1.3 (OUT), TLS handshake, Client hello (1): 
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt 
*  CApath: none 
* TLSv1.3 (IN), TLS handshake, Server hello (2): 
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1): 
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): 
* TLSv1.3 (IN), TLS handshake, Certificate (11): 
* TLSv1.3 (IN), TLS handshake, CERT verify (15): 
* TLSv1.3 (IN), TLS handshake, Finished (20): 
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): 
* TLSv1.3 (OUT), TLS handshake, Finished (20): 
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS 
* ALPN: server accepted http/1.1 
* Server certificate: 
*  subject: CN=metabolism.logophilia.eu 
*  start date: Jun  6 00:26:43 2026 GMT 
*  expire date: Sep  4 00:26:42 2026 GMT 
*  subjectAltName: host "metabolism.logophilia.eu" matched cert's "metabolism.logophilia.eu" 
*  issuer: C=US; O=Let's Encrypt; CN=YR2 
*  SSL certificate verify ok. 
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 3: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption 
* Connected to metabolism.logophilia.eu (75.119.134.68) port 443 
* using HTTP/1.x 
> GET / HTTP/1.1 
> Host: metabolism.logophilia.eu 
> User-Agent: curl/8.12.1 
> Accept: */* 
>  
* Request completely sent off 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): 
< HTTP/1.1 200 OK 
< Date: Sat, 06 Jun 2026 02:52:36 GMT 
< Server: Apache 
< Last-Modified: Sat, 06 Jun 2026 01:25:19 GMT 
< ETag: "1325f-6538ba67ff892" 
< Accept-Ranges: bytes 
< Content-Length: 78431 
< Content-Type: text/html; charset=UTF-8 
<  
<!doctype html> 
<html lang="en" data-bs-theme="auto"> 
<head> 
  <title> 
    metabolism.logophilia.eu &mdash;  Domain welcome page for  </title> 
  <meta charset="utf-8">
……


你好,

我自己检查了你的网站。看起来你的托管服务提供商正在占用 443 端口以显示此欢迎页面。你需要弄清楚如何完全释放 443/80 端口,以便 Discourse 能够控制它们。

我已经这样做了,VPS 使用 Virtualmin 管理,只是一个复选框。不幸的是,当我取消勾选“启用网站”时,无法从主机 curl 443/80 端口,而 Discourse 安装程序仍然报同样的错误。所以我决定重新启用网站,这样至少可以证明 SSL 握手是有效的。
正如我在原始帖子中所示,Discourse 安装程序最初声称 443 端口是可用的。这是我的首次安装,我将其理解为:一切正常。那么为什么安装程序会“改变主意”呢?
不过,我也不必理解每一个细节。只是想说明:即使在子域名上禁用了 Apache,Discourse 安装程序的结果也是一样的。

感谢您抽出时间。如果需要我提供任何进一步的说明,我几乎愿意做任何事。

我在自己的家用服务器上也遇到了同样的问题:

我认为,如果您 100% 确定 DNS 配置正确且端口工作正常,只需执行以下操作即可解决:

./install-discourse --skip-connection-test

谢谢,这似乎奏效了!:purple_heart:

脚本现在已超过 5/5,并且似乎正在上传/安装大量额外内容。SSL 证书现在显示错误,我想它可能在等待 TTL 超时,或者也许在设置完成后就会正常。

虽然我对 Discourse、Docker 甚至 Ruby 都一无所知……但 DNS 方面从来都不是问题 :slightly_smiling_face: 再次感谢!

我看到它已经被标记为解决方案。不过,如果方便的话,我还有一个问题。

我知道需要 PostgreSQL,但在以下地址中并未提及:

https://github.com/discourse/discourse/blob/main/docs/INSTALL-cloud.md

因此,我原本以为 Docker 镜像中已预装了 PostgreSQL。能否请您澄清一下,我是否需要在 VPS 上自行安装 PostgreSQL?因为安装说明中并未提到这一点。

……或者,也许 Docker 镜像中确实包含了 PostgreSQL,但脚本在某种情况下失败了?因为它在最后关闭了:

........
I, [2026-06-06T04:23:49.114769 #1]  INFO -- : File > /etc/runit/1.d/install-ssl  chmod: +x  chown: 
I, [2026-06-06T04:23:49.114999 #1]  INFO -- : Replacing # after ssl with if [ -z "$DISABLE_LETSENCRYPT" ] || [ -n "$ENABLE_LETSENCRYPT" ]; then
  /usr/local/bin/configure-ssl
  exec /usr/local/bin/configure-letsencrypt
fi
# after ssl in /etc/runit/1.d/install-ssl
I, [2026-06-06T04:23:49.125964 #1]  INFO -- : File > /usr/local/bin/configure-ssl  chmod: +x  chown: 
I, [2026-06-06T04:23:49.127031 #1]  INFO -- : > curl https://raw.githubusercontent.com/acmesh-official/acme.sh/3.0.6/acme.sh > /opt/acme.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  215k  100  215k    0     0   635k      0 --:--:-- --:--:-- --:--:--  637k
I, [2026-06-06T04:23:49.514883 #1]  INFO -- : > chmod +x /opt/acme.sh
I, [2026-06-06T04:23:49.554670 #1]  INFO -- : File > /usr/local/bin/configure-letsencrypt  chmod: +x  chown: 
I, [2026-06-06T04:23:49.596808 #1]  INFO -- : File > /usr/local/bin/letsencrypt  chmod: +x  chown: 
I, [2026-06-06T04:23:49.598926 #1]  INFO -- : > echo "Beginning of custom commands"
Beginning of custom commands
I, [2026-06-06T04:23:49.605809 #1]  INFO -- : > echo "End of custom commands"
End of custom commands
I, [2026-06-06T04:23:49.608842 #1]  INFO -- : Terminating async processes
I, [2026-06-06T04:23:49.609015 #1]  INFO -- : Sending INT to HOME=/var/lib/postgresql USER=postgres exec chpst -u postgres:postgres:ssl-cert -U postgres:postgres:ssl-cert /usr/lib/postgresql/15/bin/postmaster -D /etc/postgresql/15/main pid: 44
I, [2026-06-06T04:23:49.609157 #1]  INFO -- : Sending TERM to exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf pid: 111
2026-06-06 04:23:49.609 UTC [44] LOG:  received fast shutdown request
111:signal-handler (1780719829) Received SIGTERM scheduling shutdown...
2026-06-06 04:23:49.612 UTC [44] LOG:  aborting any active transactions
2026-06-06 04:23:49.619 UTC [44] LOG:  background worker "logical replication launcher" (PID 58) exited with exit code 1
2026-06-06 04:23:49.623 UTC [53] LOG:  shutting down
2026-06-06 04:23:49.634 UTC [53] LOG:  checkpoint starting: shutdown immediate
111:M 06 Jun 2026 04:23:49.683 * User requested shutdown...
111:M 06 Jun 2026 04:23:49.683 * Saving the final RDB snapshot before exiting.
111:M 06 Jun 2026 04:23:49.698 * DB saved on disk
111:M 06 Jun 2026 04:23:49.700 # Redis is now ready to exit, bye bye...
2026-06-06 04:23:49.711 UTC [53] LOG:  checkpoint complete: wrote 87 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.041 s, sync=0.022 s, total=0.088 s; sync files=52, longest=0.008 s, average=0.001 s; distance=86 kB, estimate=86 kB
2026-06-06 04:23:49.735 UTC [44] LOG:  database system is shut down

请勿安装 Postgres。

这是预期的,因为你尚未安装 Discourse 作为 Web 服务器。

那么你(几乎可以肯定)仍然存在虚拟机端口未对互联网开放的问题。

并非如此。它明确指出 Discourse 无法访问该端口。而你的 curl 命令显示有其他进程控制了 443 端口。

我认为容器已成功构建,但可能因其他进程占用了 443 端口而无法启动,或者因为 443 端口被路由到其他位置而没有任何响应。

你可以尝试运行

docker ps

查看是否有容器正在运行,以及运行

docker logs app

查看 Discourse 通过 Docker 记录的日志。

感谢反馈,真的很感激您花时间。虽然这么说有点自作聪明,但:

[2/5] 正在准备配置
✓ 端口 80 和 443 可供使用

确实一开始就显示“可供使用”。不过,在 Gemini 的帮助下(主要是关于 Docker 的各种用法,哈哈),我的实例现在已经正常运行了。我想为其他 Virtualmin 用户提供我的“运行手册”,因为:“释放 443 端口”并不是这里的解决方案。我接下来的内容就是这份手册。如果我觉得应该把它发到其他地方,比如新线程,请告诉我该去哪里;我想不止我一个人有这种设置,这对其他人可能也有用。再次感谢!

如果您使用的是由 Webmin/Virtualmin 管理的 VPS,并且使用了子域名:

终极 Virtualmin + Discourse 运行手册 *

  • (1) 清理残留(如果是重试,像我之前那样):

    rm -rf /var/discourse/shared/standalone/ssl/*

    rm -rf /var/discourse/shared/standalone/letsencrypt

    rm -rf /var/discourse/shared/standalone/state

  • (2) 删除模板:

    您必须完全删除app.yml 中的 templates/web.ssl.template.ymltemplates/web.letsencrypt.ssl.template.yml 行。即使前面加了 #,自定义的启动器解析器仍然会评估它们。

  • (3) 电子邮件设置与变量:

    DISCOURSE_SKIP_EMAIL_SETUP'1' 改为 '0',因为否则您的 Discourse 将无法连接并检查 DiscordID;

    添加 DISCOURSE_FORCE_HTTPS: true,以便后端生成安全的 URL。

    温馨提示:确保您的 DISCOURSE_SMTP_USER_NAME 设置为您的原始邮箱账户名(例如 'logophilia'),而不是完整的电子邮件地址(例如 'logophilia@logophilia.eu'),并将凭实用单引号(')括起来,以绕过潜在的 YAML 字符解析错误。

  • (4) 暴露块配置:

    确保您的 app.yml 中的 expose: 块包含一个 HTTP 映射;映射 443=>8443 是可选的/多余的,因为 Virtualmin 在传递之前已经终止了 SSL 逻辑:

    expose:
      - 8080:80
    

    现在您可以开始重建了:

    cd /var/discourse
    ./launcher rebuild app
    
  • (5) 子域名和代理路径设置:

    • 像往常一样在 Virtualmin 中创建您的子域名,并用 Let’s Encrypt SSL 证书保护它(自动完成,只是提醒:确保不会因为任何无关原因报错)。
    • 导航到代理路径(Virtualmin → 您的子域名 → Web 配置 → 代理路径),创建一个新的映射 /http://localhost:8080/,保持“本地服务”未勾选,但将代理 WebSocket 切换为,以允许实时更新和通知流。
  • (6) CSRF 头指令:

    • Webmin ➔ 服务器 ➔ Apache Webserver ➔ [找到您的子域名配置并点击 443 的配置] ➔ 编辑指令 中,将以下行放在 Virtualmin 自己的 Let’s Encrypt 代理块上方(通常是 ProxyPass /.well-known !),以促进 CSRF 令牌的转发:
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
    

    ProxyPreserveHost On:告诉 Discourse 您的实际域名,而不是“localhost”。
    RequestHeader set X-Forwarded-Proto "https":明确告诉 Discourse 用户正在使用安全连接,与您的 DISCOURSE_FORCE_HTTPS: true 设置相匹配。
    RequestHeader set X-Forwarded-For:将访问者的真实 IP 地址传递给容器,以便安全日志正常工作。

  • (7) 干净的容器握手:

    在漫长的(抱歉……但这是真的;-) 重建过程完成时,确保使用 docker rm -f app 清除任何可能卡住的容器蓝图,这样运行 ./launcher start app 就会启动一个完全绑定到端口 8080 的全新实例。检查 docker ps 是否在“端口”下显示类似以下内容:

    # docker ps
    CONTAINER ID   IMAGE                 COMMAND        CREATED          STATUS          PORTS                                                                                NAMES
    d21772a21e36   local_discourse/app   "/sbin/boot"   45 minutes ago   Up 45 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp, 0.0.0.0:8443->443/tcp, [::]:8443->443/tcp   app
    

    (如您所见,我在 app.yml 中保留了 443=>8443 指令,两种方式都可以。)

  • (8) 监控与启动:

    使用 docker logs -f app 跟踪启动流,直到数据库迁移完成且工作人员开始处理请求。基本上就是一连串的快速出现的“INFO”行。

  • (9) 最终化:

    在浏览器中加载您的子域名,点击注册,让系统向您的邮箱发送验证邮件。

*)直到被证明是错误的 :wink:

在安装之前,我需要关闭 Nginx 服务器。不过很高兴看到有一个标志可以跳过此测试,:)。