DigitalOcean Droplet上Discourse与静态站点Let's Encrypt证书冲突求助
嘿,我之前也碰到过一模一样的问题!同一台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处理:
- 打开Discourse的
app.yml文件(在/var/discourse/containers/目录下) - 找到
expose部分,把443删掉,改成8080(或者保留80和8080) - 把
ssl: true改成ssl: false,关闭容器内部的SSL - 重建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

