Nginx配置SSL证书完整教程:生产环境HTTPS部署指南
Nginx配置SSL证书完整教程:生产环境HTTPS部署指南
Nginx是生产环境部署HTTPS的首选Web服务器,性能高、配置灵活。但Nginx的SSL配置项很多,配置不当会影响安全性和性能。这篇把Nginx配置SSL证书的完整流程讲清楚,包含安全配置、性能优化和故障排查。
第一步:申请SSL证书
在 sslmianfei.com 在线申请ZeroSSL免费证书,下载得到:
- •
fullchain.crt(证书文件,包含服务器证书和中间证书) - •
private.key(私钥文件)
注意:必须使用fullchain(包含中间证书),如果只下载了服务器证书,需要手动合并:
cat yourdomain.crt intermediate.crt > fullchain.crt
第二步:放置证书文件
推荐存放路径:/etc/nginx/ssl/
# 创建证书目录
mkdir -p /etc/nginx/ssl/
# 把证书文件放到该目录
# 假设证书文件已上传到 /root/ 目录
cp /root/fullchain.crt /etc/nginx/ssl/yourdomain.crt
cp /root/private.key /etc/nginx/ssl/yourdomain.key
# 设置正确的权限
chmod 644 /etc/nginx/ssl/yourdomain.crt
chmod 600 /etc/nginx/ssl/yourdomain.key
chown -R nginx:nginx /etc/nginx/ssl/
权限说明:
- •证书文件(.crt)权限644:所有用户可读
- •私钥文件(.key)权限600:只有属主可读
- •属主设为nginx用户,确保Nginx能读取
第三步:配置Nginx HTTPS
基础配置
编辑网站配置文件(通常在 /etc/nginx/conf.d/ 或 /etc/nginx/sites-available/):
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/yourdomain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
# 网站根目录
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP解析(如果使用PHP)
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# HTTP 301跳转到HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
安全增强配置
完整的SSL安全配置:
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL证书
ssl_certificate /etc/nginx/ssl/yourdomain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
# TLS版本(只启用1.2和1.3)
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# SSL会话缓存(提升性能)
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP装订(加速TLS握手)
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# HSTS(强制浏览器使用HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 安全响应头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 网站根目录
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# HTTP 301跳转到HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
第四步:验证配置并重启
验证配置语法
nginx -t
输出示例:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
如果有错误,根据错误提示修改配置文件。
重新加载Nginx
# 重新加载配置(不中断服务)
nginx -s reload
# 或
systemctl reload nginx
# 或重启Nginx(会短暂中断服务)
systemctl restart nginx
验证HTTPS
# 本机测试HTTPS
curl -I https://localhost/
# 测试证书链
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
# 在线检测
# 用 https://www.sslmianfei.com/cert-tester/ 检测
第五步:配置HTTP/2
HTTP/2强制要求HTTPS,开启后能显著提升页面加载速度。
确认Nginx支持HTTP/2
nginx -V 2>&1 | grep -o http_v2_module
如果输出 http_v2_module,说明支持HTTP/2。如果没有,需要重新编译Nginx。
开启HTTP/2
在listen指令后添加 http2:
listen 443 ssl http2;
注意:HTTP/2必须在443端口的server块中开启,不能在80端口开启。
验证HTTP/2
# 用curl测试HTTP/2
curl -I --http2 https://yourdomain.com/
# 或用Chrome开发者工具
# F12 → Network → 右键列头 → 勾选Protocol → 查看是否显示h2
多域名配置(SNI)
一台服务器上部署多个HTTPS网站,需要配置SNI。
# 站点1
server {
listen 443 ssl http2;
server_name site1.com;
ssl_certificate /etc/nginx/ssl/site1.crt;
ssl_certificate_key /etc/nginx/ssl/site1.key;
root /var/www/site1;
location / {
try_files $uri $uri/ /index.php?$args;
}
}
# 站点2
server {
listen 443 ssl http2;
server_name site2.com;
ssl_certificate /etc/nginx/ssl/site2.crt;
ssl_certificate_key /etc/nginx/ssl/site2.key;
root /var/www/site2;
location / {
try_files $uri $uri/ /index.php?$args;
}
}
关键点:每个server块的server_name必须和证书的域名一致,每个站点使用自己的证书。
通配符证书配置
如果使用通配符证书(*.yourdomain.com),可以覆盖所有二级子域名:
server {
listen 443 ssl http2;
server_name *.yourdomain.com;
ssl_certificate /etc/nginx/ssl/wildcard.crt;
ssl_certificate_key /etc/nginx/ssl/wildcard.key;
# 根据子域名动态指定根目录
set $subdomain "";
if ($host ~* "^([^.]+)\.yourdomain\.com$") {
set $subdomain $1;
}
root /var/www/$subdomain;
location / {
try_files $uri $uri/ /index.php?$args;
}
}
证书自动续期
免费证书90天有效期,建议用acme.sh自动续期。
安装acme.sh
curl https://get.acme.sh | sh
申请证书(DNS验证)
# 阿里云DNS
export Ali_Key="your_aliyun_key"
export Ali_Secret="your_aliyun_secret"
acme.sh --issue --dns dns_ali -d yourdomain.com -d www.yourdomain.com
# 腾讯云DNSPod
export Tx_Secret="your_tencent_secret"
export Tx_Key="your_tencent_key"
acme.sh --issue --dns dns_tencent -d yourdomain.com -d www.yourdomain.com
# Cloudflare
export CF_Key="your_cf_key"
export CF_Email="your_email@example.com"
acme.sh --issue --dns dns_cf -d yourdomain.com -d www.yourdomain.com
安装证书到Nginx
acme.sh --install-cert -d yourdomain.com \
--key-file /etc/nginx/ssl/yourdomain.key \
--fullchain-file /etc/nginx/ssl/yourdomain.crt \
--reloadcmd "systemctl reload nginx"
acme.sh会自动创建cron定时任务,每60天自动续期一次,完全无人值守。
常见问题排查
问题一:Nginx启动失败
原因:配置语法错误,或证书文件路径不对。
解决:
# 检查配置语法
nginx -t
# 查看错误日志
tail -f /var/log/nginx/error.log
问题二:浏览器报”证书不受信任”
原因:证书链不完整,缺少中间证书。
解决:
- •确认使用的是fullchain.crt而不是单独的服务器证书
- •用 SSL检测工具 检测证书链
- •重新部署包含中间证书的fullchain
问题三:HTTPS访问502错误
原因:Nginx无法连接到后端PHP-FPM。
解决:
# 检查PHP-FPM是否运行
systemctl status php-fpm
# 或
systemctl status php7.4-fpm
# 检查9000端口是否监听
netstat -tlnp | grep :9000
# 检查fastcgi_pass配置
# 如果PHP-FPM监听unix socket,修改为:
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
问题四:HTTP跳转HTTPS循环
原因:CDN或反向代理模式下,Nginx收到了HTTP请求(CDN解密后是HTTP),又触发跳转到HTTPS,形成循环。
解决:
- •检查CDN的回源协议配置
- •如果使用CDN,关闭源站的HTTP跳转,由CDN处理跳转
- •或配置Nginx识别
X-Forwarded-Proto头
问题五:HTTP/2没生效
原因:Nginx未编译HTTP/2模块,或配置错误。
解决:
# 检查Nginx是否支持HTTP/2
nginx -V 2>&1 | grep http_v2_module
# 如果没有,需要重新编译Nginx
./configure --with-http_v2_module ...
问题六:证书和私钥不匹配
原因:证书文件和私钥文件不是同一套。
解决:
# 验证证书和私钥是否匹配
openssl x509 -noout -modulus -in yourdomain.crt | openssl md5
openssl rsa -noout -modulus -in yourdomain.key | openssl md5
# 两个md5值必须一致
问题七:443端口被占用
原因:其他程序占用了443端口。
解决:
# 查看占用443端口的程序
netstat -tlnp | grep :443
# 杀掉占用进程
kill -9 <PID>
性能优化建议
启用SSL会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
效果:减少TLS握手次数,提升页面加载速度。
启用OCSP装订
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
效果:客户端不需要单独查询OCSP服务器,加速TLS握手。
只启用TLS 1.2和1.3
ssl_protocols TLSv1.2 TLSv1.3;
效果:禁用不安全的旧版本,提升安全性。
使用ECDHE加密套件
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
效果:支持前向安全性,即使私钥泄露,历史流量也无法被解密。
配置验证
部署完成后,用以下工具验证配置:
- SSL证书配置检测工具:https://www.sslmianfei.com/cert-tester/
- •检测证书链是否完整
- •检测TLS版本是否安全
- •检测证书品牌和有效期
- •检测安全响应头
- 命令行验证:
# 测试TLS 1.2
openssl s_client -connect yourdomain.com:443 -tls1_2
# 测试TLS 1.3
openssl s_client -connect yourdomain.com:443 -tls1_3
# 查看证书详情
openssl s_client -connect yourdomain.com:443 -showcerts
总结
Nginx配置SSL证书的核心步骤:
- 在 sslmianfei.com 申请免费SSL证书
- 放置证书文件到
/etc/nginx/ssl/ - 配置Nginx的HTTPS server块
- 配置HTTP 301跳转到HTTPS
- 配置安全响应头(HSTS、X-Frame-Options等)
- 配置SSL会话缓存和OCSP装订
- 开启HTTP/2
- 验证配置并reload Nginx
- 用 SSL检测工具 验证
关键配置项:
- •
ssl_protocols TLSv1.2 TLSv1.3;:只启用安全版本 - •
ssl_session_cache:提升性能 - •
ssl_stapling on;:加速TLS握手 - •
add_header Strict-Transport-Security:强制HTTPS - •
listen 443 ssl http2;:开启HTTP/2
生产环境推荐方案:
- •Nginx + acme.sh自动续期
- •TLS 1.2 + TLS 1.3
- •HTTP/2开启
- •HSTS开启
- •安全响应头配置完整
如果配置后无法访问HTTPS,可以参考 部署SSL证书后无法访问HTTPS的原因总结 排查问题。