核心是“一域名一server块一证书”,即每个域名必须配置独立server块,显式声明listen 443 ssl、匹配的server_name、绝对路径的ssl_certificate与ssl_certificate_key,私钥权限600,且不可用if或全局http块复用证书。

在 Nginx 中管理多个虚拟主机的 SSL 证书,核心是“一域名一 server 块一证书”,不能靠条件判断切换证书,也不能把证书配置提到 http 全局块。只要结构清晰、路径明确、权限合规,就能稳定支撑多个 HTTPS 站点共存于同一 IP。
每个域名配独立 server 块
不同域名必须各自拥有完整的 server 块,且都监听 443 端口并启用 ssl。server_name 必须与证书主体(CN)或 SAN 字段完全一致。
- 写法示例:
server {<br> listen 443 ssl http2;<br> server_name example.com www.example.com;<br> ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;<br> ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;<br> root /var/www/example.com;<br> } - blog.example.com、shop.example.com 等子域或独立域名,都要另起一个 server 块,不能合并到同一个块里用 if 判断 host
- 多个域名共用通配符证书(如 *.example.com)时,仍需确保 server_name 匹配该证书覆盖范围;跨主域(如 site-a.com 和 site-b.net)必须用各自专属证书
证书路径与文件权限要严格对应
证书和私钥路径必须写绝对路径,Nginx 不会自动补全或按工作目录查找;私钥权限过高会导致启动失败。
- 推荐统一存放位置,例如:
/etc/nginx/ssl/example.com.crt/etc/nginx/ssl/example.com.key - 私钥必须设为 600:
chmod 600 /etc/nginx/ssl/example.com.key - 证书文件(.crt/.pem)一般 644 即可,确保 Nginx 主进程(通常 root)能读取
- 用 openssl 验证是否匹配:
openssl x509 -in /etc/nginx/ssl/example.com.crt -text -noout | grep "Subject Alternative Name"
确认输出中包含你声明的全部 server_name
HTTP 跳转与兜底处理不能少
避免用户访问 HTTP 或未知域名时出现异常响应,需要显式定义跳转逻辑和拦截策略。
- 每个域名都应配一个 80 端口 server,强制 301 跳转:
server {<br> listen 80;<br> server_name example.com;<br> return 301 https://$host$request_uri;<br> } - 加一个 default_server 拦截非法 SNI 请求:
server {<br> listen 443 ssl default_server;<br> server_name _;<br> return 444;<br> }
这样未命中任何 server_name 的 HTTPS 请求会被静默关闭,不暴露默认站点
验证与重载必须分步执行
SSL 配置错误会导致整个 HTTPS 服务中断,不能跳过检查直接 reload。
- 每次改完配置,先运行:
sudo nginx -t
看到 “syntax is ok” 和 “test is successful” 才继续 - 生效用:
sudo nginx -s reload
不要用 restart,避免连接中断 - 外部验证方式:
– 浏览器访问 https://example.com,点击地址栏锁图标看证书详情
– 命令行验证 SNI 是否生效:openssl s_client -connect your.ip:443 -servername example.com -showcerts 2>/dev/null | openssl x509 -noout -subject
换域名再试,应返回对应证书的 subject


















