唯一稳定可靠的做法是为每个域名配置独立的server块,各自绑定专属证书路径、精确server_name及listen 443 ssl;Nginx依赖TLS握手时SNI字段自动匹配,不支持if运行时切换证书,且ssl_certificate不可上移至http块。

直接用多个独立的 server 块,每个块绑定一个域名、一套证书,是唯一稳定可靠的做法。Nginx 依靠 TLS 握手时的 SNI(Server Name Indication)机制自动匹配,不需要 if 判断,也不允许证书配置上移至 http 全局块。
每个域名配一个完整的 HTTPS server 块
不同域名必须各自拥有独立的 server 块,且都显式监听 443 ssl。不能把多个域名塞进同一个块里靠 if ($host = ...) 切换证书——Nginx 不支持运行时 SSL 证书切换。
-
server_name必须与证书的 CN 或 SAN 字段完全一致(如example.com和www.example.com都要出现在证书中,或分别配两个块) - 通配符证书(如
*.example.com)可覆盖所有一级子域,但blog.example.com和shop.example.net仍需各自证书和各自 server 块 - 示例结构:
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
root /var/www/example.com;
}
证书路径与权限必须严格合规
Nginx 不会自动补全路径,也不会按工作目录查找证书;私钥权限过高会导致启动失败。
- 证书和私钥路径必须写绝对路径,推荐统一存放,例如:
/etc/nginx/ssl/example.com.crt/etc/nginx/ssl/example.com.key - 私钥权限必须为
600:chmod 600 /etc/nginx/ssl/example.com.key - 证书文件权限设为
644即可,确保 Nginx 主进程(通常以 root 运行)能读取 - 用 OpenSSL 验证证书是否覆盖所需域名:
openssl x509 -in /etc/nginx/ssl/example.com.crt -text -noout | grep "Subject Alternative Name"
配套 HTTP 跳转与非法请求拦截
只配 HTTPS 不够,HTTP 访问和未知域名请求必须有明确处理,否则用户可能看到错误页或默认站点。
- 为每个域名加一个 80 端口 server 块,强制 301 跳转:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
} - 加一个
default_server拦截未匹配的 SNI 请求(比如直接用 IP 访问或错填 host):
server {
listen 443 ssl http2 default_server;
server_name _;
return 444;
# 或返回自定义错误页
}
环境隔离与安全参数建议
开发、测试、生产等多环境共存时,物理隔离比逻辑判断更安全。
- 按环境分目录存放证书,如:
/etc/nginx/ssl/dev/、/etc/nginx/ssl/prod/,避免误引用 - 每个 HTTPS server 块中显式配置 TLS 参数(不依赖全局):
ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;ssl_prefer_server_ciphers off; - 生产环境建议启用:
ssl_stapling on;ssl_trusted_certificate /path/to/fullchain.pem;add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;


















