最直接的办法是手动重载 Nginx 服务,但长期解决需要在证书续签命令中加入自动重载钩子。
先说结论:证书文件更新后 Nginx 不会自动感知,必须发送重载信号或重启服务才能加载新证书。
- 先确认:检查当前线上证书有效期是否已更新
- 先处理:手动执行重载命令立即生效,配置钩子防止复发
- 再验证:通过命令行或浏览器确认新证书已加载
命令速用版
如果你需要立即恢复,执行以下命令重载 Nginx:
sudo systemctl reload nginx如果你使用的是 Certbot,建议加上部署钩子自动重载:
certbot renew `--deploy-hook` "systemctl reload nginx"为什么会这样
Nginx 通常在启动或收到重载信号时读取证书文件到内存。Let's Encrypt 续签只是更新了磁盘上的文件(通常是软链接指向的新文件),如果没有通知 Nginx,它会继续使用内存中旧的证书信息。这是 Nginx 的设计机制,旨在避免频繁读取磁盘影响性能,但也意味着配置变更需要显式通知。
分步处理
1. 确认证书状态:使用 OpenSSL 查看当前连接使用的证书日期,确认是否仍为旧证书。
2. 测试配置语法:在重载前务必测试配置,避免语法错误导致服务中断。
sudo nginx -t3. 手动重载:执行 reload 命令,不会断开现有连接,仅工作进程重启。
sudo systemctl reload nginx4. 配置自动化:检查你的定时任务(crontab 或 systemd timer),确保续签命令包含部署钩子。Certbot 默认在某些配置下会自动尝试重载,但显式指定更可靠。
Certbot 配置文件永久生效方法
为了避免每次手动输入钩子命令,可以将配置写入 Certbot 配置文件。
全局配置:编辑 `/etc/letsencrypt/cli.ini`,添加以下内容:
deploy-hook = systemctl reload nginx单域名配置:编辑 `/etc/letsencrypt/renewal/你的域名.conf`,在 `[renewalparams]` 段落下添加:
deploy_hook = systemctl reload nginx修改后无需修改定时任务,Certbot 会自动读取配置执行重载。
怎么验证是否生效
使用 openssl 命令连接服务器,查看 Certificate 字段中的 Not After 日期是否已更新为新有效期。
echo | openssl s_client -connect 你的域名:443 2>/dev/null | openssl x509 -noout -dates也可以在浏览器中点击地址栏锁图标,查看证书详细信息中的有效期。
常见坑与 Docker 环境处理
1. 权限问题:钩子脚本可能没有 sudo 权限,导致重载命令执行失败。
2. 语法错误:Nginx 配置测试失败会导致重载被拒绝,续签脚本可能误判为成功。
3. 软链接机制:Let's Encrypt 使用软链接管理证书,确保 Nginx 配置指向的是 live 路径而非 archive 路径。
4. 容器环境:如果在 Docker 中运行 Nginx,主机上的 systemctl 命令无法控制容器内进程。
- 方法一(发送信号):
docker exec -s HUP <容器名称或 ID> - 方法二(重启容器):
docker restart <容器名称或 ID> - 配置钩子:将 deploy-hook 设置为上述 docker 命令,注意可能需要配置 sudo 免密。
参考来源
Let's Encrypt Official Documentation: https://letsencrypt.org/docs/
Certbot Instructions: https://certbot.eff.org/
Nginx Official Documentation: https://nginx.org/en/docs/http/ngx_http_ssl_module.html