You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DigitalOcean Droplet上Discourse与静态站点Let's Encrypt证书冲突求助

解决Discourse与静态站点的Let's Encrypt证书SNI冲突问题

嘿,我之前也碰到过一模一样的问题!同一台Droplet上跑多个HTTPS站点时,最容易踩SNI(Server Name Indication)配置的坑——Web服务器没根据请求域名正确匹配证书,就会出现你说的静态站被识别成Discourse证书的情况。下面一步步来排查解决:

1. 先明确你的Web服务架构

首先得搞清楚两个站点是怎么共用443端口的,分两种常见情况:

情况A:主机Nginx同时代理Discourse和托管静态站

这是最推荐的配置,先检查Nginx的站点配置(一般在/etc/nginx/sites-available/目录下的两个.conf文件):

  • 每个server块必须明确写对server_name,比如Discourse的是discourse.yourdomain.com,静态站的是static.yourdomain.com
  • 每个server块里的ssl_certificate和ssl_certificate_key必须指向各自域名的Let's Encrypt证书,别搞混路径!比如静态站的证书应该是/etc/letsencrypt/live/static.yourdomain.com/fullchain.pem,对应密钥是同目录的privkey.pem
  • 别让全局的SSL配置(比如nginx.conf里的http块)覆盖了站点级的证书设置

给你个正确的配置示例参考:

# Discourse的反向代理配置
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name discourse.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/discourse.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/discourse.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://localhost:8080; # Discourse容器默认监听8080
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# 静态站点的配置
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name static.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/static.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/static.yourdomain.com/privkey.pem;

    root /var/www/your-static-site; # 静态文件所在目录
    index index.html index.htm;
}

情况B:Discourse容器直接占用了443端口

如果Discourse自己的Nginx容器直接绑定了主机的443端口,那静态站的HTTPS请求根本到不了自己的服务,全被Discourse接走了,自然会返回它的证书。这时候得改Discourse的配置,把SSL交给主机Nginx处理:

  1. 打开Discourse的app.yml文件(在/var/discourse/containers/目录下)
  2. 找到expose部分,把443删掉,改成8080(或者保留80和8080)
  3. 把ssl: true改成ssl: false,关闭容器内部的SSL
  4. 重建Discourse容器:./launcher rebuild app
    然后回到情况A的配置,用主机Nginx统一代理两个站点。

2. 验证证书本身没问题

别光看配置,先确认证书是对的:

  • 运行ls -l /etc/letsencrypt/live/,看看两个域名的目录都在不,里面的fullchain.pem和privkey.pem有没有权限问题(一般要让Nginx能读取,权限设为644就行)
  • 用openssl x509 -in /etc/letsencrypt/live/[静态站域名]/fullchain.pem -text -noout查看证书内容,确认Subject Alternative Name里确实包含你的静态站域名,别生成错了证书

3. 重启服务+测试

改完配置一定要重启Nginx:sudo systemctl restart nginx
然后用curl测试一下,模拟静态站的请求:curl -v -H "Host: static.yourdomain.com" https://localhost,看输出里的证书信息是不是对应静态站的。
最后再跑一遍SSLLabs的检测,应该就能看到SNI匹配正确了。

4. 别忘了排查缓存/CDN

如果你的站点用了Cloudflare这类CDN,要检查CDN的SSL模式是不是设成了Full(Strict),并且CDN那边已经更新了最新的证书——有时候CDN会缓存旧证书,导致你改了服务器配置后,外面看还是老样子。


内容的提问来源于stack exchange,提问作者toonday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:59:47