解决自动更新SSL证书的缓存问题

橘子 发布于 2025-02-28 270 次阅读


如果看过我三个月前的一篇文章,如何自动化更新SSL证书,那么应该可以解决自动化更新SSL证书的问题了。然而,自动申请的SSL证书只有90天有效期——没错,我写当前这篇文章恰好是过去了三个月,就在昨天证书过期了!今天就发现不能正常https访问网站!

事件原因分析

已知信息:(1)我使用nginx做代理。(2)在旧的证书将要过期时,脚本会自动申请新的证书并且覆盖旧文件,而不保留旧的文件。

然而,使用浏览器访问时,提示https证书已经过期,经过检查我发现这是因为浏览器接收到的还是旧的证书。我检查了服务器的文件,发现证书文件已经是新的了,因此我怀疑是缓存问题,于是刷新浏览器,没有用;然后重启nginx服务,有用了,此时浏览器可以使用新的证书访问网页了。

这就说明应该是nginx代理没有在证书文件更新后,重新读取新文件,还在使用旧文件缓存而导致的错误。

解决方法

回顾如何自动化更新SSL证书一文,应该知道acme.sh会使用crontab完成证书的自动更新任务。因此,只需要在证书更新后,让nginx重新加载一遍配置就好了!可以配合之前写过的《使用crontab设置服务器定时任务》教程来完成就好了。

首先使用如下命令可以查看当前用户所有的定时任务:

#!/usr/bin/bash
crontab -l

然后能找到这一条任务:

31 23 * * * "/home/ubuntu/.acme.sh"/acme.sh --cron --home "/home/ubuntu/.acme.sh" > /dev/null

回顾之前的教程,这个任务的意思是会在每天的23:31执行acme.sh脚本来更新证书。由于脚本可能会更新,因此不便于直接修改脚本的内容。所以在这里我们新建一个任务,让它在23:35自动重新加载nginx配置。由于脚本会自动提前一个月申请下一轮新证书,所以不用担心这中间间隔的4分钟内没有证书可用。

使用如下命令打开当前用户的定时任务,进行编辑(如果需要修改默认编辑器等参考前文内容):

crontab -e

加入如下任务:

35 23 * * * sudo /usr/sbin/nginx -s reload

注意事项

使用reload命令时,会平滑的过度。也就是说,在执行reload时某个服务仍然有用户连接,那么nginx会等待这个用户的服务结束后,再关闭这个旧的服务,并且这个服务在重启前不会接受新的服务。具体机制更加复杂。

reload比较优雅,在使用新配置前,会对配置做检查,如果出现问题会放弃重启,并且继续使用旧的配置。在上述代码中,没有处理错误输出。如果你担心配置没有生效、不确定任务是否有正常运行,其实可以使用如下任务来进行检查:

21 20 * * * sudo /usr/sbin/nginx -t && sudo /usr/sbin/nginx -s reload >> /home/ubuntu/temp.log 2>&1 && echo "Nginx reload successful at $(date)" >> /home/ubuntu/temp.log || echo "Nginx reload failed at $(date)" >> /home/ubuntu/temp.log

这段代码的意思是说,在20:21执行任务(选择方便的时间)。首先nginx -t 会检查配置文件,如果成功,则继续执行 nginx -s reload,并将输出写入日志。如果 nginx -s reload 成功执行,追加“成功”的信息到日志文件中;如果失败,追加“失败”的信息到日志文件中。

此外,reload不能解决一些restart能解决的问题,例如如果监听的ip发生了变化,可能需要使用restart。

此外,如果sudo命令需要输入密码、不能在定时任务中正常使用sudo,则说明没有配置无密码使用sudo。这个需要使用visudo命令修改对应的权限,我参考了这篇博客进行检查——腾讯云服务是会自动给ubuntu用户添加的,所以不用自己管这件事。