Nginx 替换 SSL 证书不生效?一次完整的排查与实战总结
在实际部署中,我们经常会遇到这样一个问题:
明明已经把新的 SSL 证书上传到了服务器并替换了 Nginx 配置文件中的路径,为什么浏览器访问时显示的仍然是旧证书?
本文将从根本原因入手,详细剖析证书替换后不生效的常见原因,给出完整的排查方案,并附带实用命令,助你快速定位并解决问题。
一、证书加载失败的典型错误
当 Nginx 无法正确加载 SSL 证书时,通常会报出如下错误:
bash
nginx: [emerg] SSL_CTX_use_certificate:ee key too small
nginx: [emerg] cannot load certificate "/etc/nginx/ssl/server.crt": PEM lib
或者:
bash
unable to load certificate
140735281173760:error:0906D06C:PEM routines:PEM_read_bio:no start line:...
Expecting: TRUSTED CERTIFICATE
这说明:Nginx 或 OpenSSL 无法识别你提供的证书文件,原因可能包括格式错误、证书链不完整、权限不正确等。
二、替换证书后的正确操作流程
✅ 步骤 1:确认证书文件是 PEM 格式
Nginx 只接受 PEM 格式的证书:
- 以
-----BEGIN CERTIFICATE-----
开头 - 是 文本文件 而非二进制格式
🔍 检查命令:
bash
cat /etc/nginx/ssl/server.crt
若证书是 .der
或 .pfx
格式,请使用 OpenSSL 转换:
bash
# DER -> PEM
openssl x509 -inform DER -in your_cert.der -out your_cert.pem
# PFX -> PEM
openssl pkcs12 -in your_cert.pfx -clcerts -nokeys -out your_cert.pem
✅ 步骤 2:确认证书文件已被成功替换
bash
ls -l /etc/nginx/ssl/server.crt
openssl x509 -in /etc/nginx/ssl/server.crt -noout -dates
检查证书的生效时间(notBefore
)与过期时间(notAfter
)是否是你预期的新证书信息。
✅ 步骤 3:验证证书是否与私钥匹配
bash
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
如果两者 MD5 值不同,说明证书和私钥不匹配,必须重新签发。
✅ 步骤 4:确保中间证书链完整(CA Bundle)
很多证书是由中间 CA 签发的,必须将中间证书追加到主证书文件:
bash
cat your_domain.crt intermediate.crt > /etc/nginx/ssl/server.crt
🔍 验证证书链:
bash
openssl verify -CAfile ca_bundle.crt your_domain.crt
✅ 步骤 5:检查 Nginx 配置是否正确引用新证书
nginx
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
...
}
运行以下命令测试语法是否正确:
bash
sudo nginx -t
✅ 步骤 6:让 Nginx 生效配置
Nginx 不会自动加载新证书,必须手动触发配置重载或重启:
bash
# 推荐方式:不影响现有连接
sudo nginx -s reload
# 如果无效,可强制重启(会短暂中断服务)
sudo systemctl restart nginx
三、证书更新后仍显示旧证书?常见问题排查
问题 | 原因分析 | 解决方法 |
---|---|---|
证书未实际替换 | 上传了新证书但路径指向仍是旧文件或内容未被覆盖 | ls -l 检查时间戳;使用 openssl x509 -in ... 检查内容 |
Nginx 未 reload | 修改证书后未执行 reload 或 restart |
执行 nginx -s reload 或 systemctl restart nginx |
缓存问题(浏览器/CDN) | 客户端或 CDN 缓存了旧证书 | 使用无痕窗口访问、清除缓存或绕过 CDN 测试 |
中间证书缺失 | 只部署了主证书,未附带中间证书 | 合并证书链为一个文件后部署 |
证书权限不正确 | Nginx 无法读取证书文件或私钥 | 设置正确的读权限和属主 |
使用了错误的 server 块 |
有多个 server_name ,配置未命中 |
使用正确的 server_name 与 listen 块 |
四、验证证书是否已真正生效
1. OpenSSL 方式验证:
bash
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com | openssl x509 -noout -dates
2. 使用 curl
验证证书信息:
bash
curl -vI https://yourdomain.com
3. 浏览器验证:
在浏览器中打开网站,点击证书图标 → 查看证书 → 查看有效期和颁发者是否更新。
五、自动化建议:Let's Encrypt + 定期 Reload
如果你使用 Certbot 自动续签,可以加一个 post-hook
来自动 reload Nginx:
bash
sudo certbot renew --post-hook "systemctl reload nginx"
六、总结:替换证书后生效的关键点
步骤 | 操作命令/说明 | |
---|---|---|
确保新证书为 PEM 格式 | openssl x509 -in xxx -noout -text |
|
确认证书已正确覆盖 | ls -l 、openssl x509 -in ... -dates |
|
确认证书与私钥匹配 | `openssl x509 | rsa -modulus+ md5` |
合并中间证书(如有) | cat domain.crt intermediate.crt > server.crt |
|
测试 Nginx 配置语法 | nginx -t |
|
重载或重启 Nginx 服务 | nginx -s reload / systemctl restart nginx |
|
检查是否真正生效 | openssl s_client / 浏览器证书信息 |
如果你在生产环境中部署 HTTPS 站点,请务必对证书更新和 reload 流程保持熟悉,避免因证书错误导致服务不可用或用户无法访问。