SSL 证书续订

上一篇博客 提到了使用 Let’s Encrypt 获取 SSL 证书的过程,由于其提供的免费证书有效期只有 3 个月,因此需要定期执行续订操作。

按照官方教程,只需要使用 Let’s Encrypt 提供的证书管理工具 certbot,执行certbot renew就可以自动续订,但很不幸的是今天尝试后收到了一串无情的报错信息。

nginx: [error] invalid PID number "" in "/var/run/nginx.pid"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/sszxc.net/fullchain.pem (failure)

由此想到重启一下 nginx ,但是使用nginx -c命令重新加载 nginx 配置文件也会报错。

root@sszxc:/etc/nginx# nginx -c /etc/nginx/nginx.conf 
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
nginx: [emerg] still could not bind()

使用lsof -i:80查看 80 端口的占用情况,发现是 nginx 它自己,这样看来可能的原因是上一次 nginx 没有正常关闭,所以导致端口一直被占用着了。使用sudo fuser -k 80/tcp杀掉占用 80 端口的进程,然后就可以顺利重启 nginx 了,这之后使用certbot renew即可顺利自动续订。

Processing /etc/letsencrypt/renewal/sszxc.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for sszxc.net
http-01 challenge for www.sszxc.net
Waiting for verification...
Cleaning up challenges
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of nginx server; fullchain is
/etc/letsencrypt/live/sszxc.net/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/sszxc.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Crontab 定时任务

为了自动化续订操作,这里可以使用 Crontab 程序定时执行命令。Vultr 提供的 VPS 内置了 Crontab 程序,如果手动安装的话命令如下:

yum install vixie-cron crontabs
Crontab chkconfig crond on
service crond start

说明:vixie-cron 软件包是 cron 的主程序;crontabs 软件包是用来安装、卸装、 或列举用来驱动 cron 守护进程的表格的程序。三行命令分别是安装、设为开机自启动和手动启动 Cron 服务。

可以使用service cron status检查 Cron 服务状态,使用crontab -e创建 Cron 文件,使用sudo crontab -l查看修改完成后的定时命令。

root@sszxc:/etc/nginx# crontab -e
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /bin/ed

Choose 1-4 [1]:

选择一个编辑器之后即可进入如下编辑界面。

Cron 文件编辑

仔细研究上面的注释后了解到,每一行定义一个单独的命令,前五个参数分别表示分钟、小时、一个月中的第几天、月份、一周中的第几天,使用*可以表示通配符。

举例来说,可以用“30 4 1,7,21,28 * * ”几个参数表示每月的 1,7,21,28 号的 4 点 30 分,而上图中的命令就可以表示每月 1 日的凌晨 3 点执行一次证书的续期操作,并重启 Nginx

为了验证,我先设定了一个 5 分钟后执行的任务,但可惜的是摸鱼回来之后发现证书的认证时间并没有更新,测试失败。

在论坛里查找了一些资料后了解到,Let’s Encrypt 的日志存储在 /var/log/letsencrypt 下,转到其目录下后使用tail -n 50 letsencrypt.log检查最新的 50 条日志,在密密麻麻的信息中发现了Cert not yet due for renewal的提示,也就是说 Crontab 程序能够正常触发,然而 Let’s Encrypt 并没有成功续期。

继续 Google 之后了解到在 /etc/letsencrypt/renewal 目录下,可以找到站点的 renewal 的配置文件。

renewal 配置文件

可以看到第一行的 renew_before_expiry = 30 days 。意思是,距离证书到期时间为 30 天以内的时候,执行更新证书的命令certbot renew才会更新证书,所以前一次测试自然是不会成功了。

最后可以使用certbot certificates查看当前的所有的证书信息,可以看到有效期还剩 89 天。

root@sszxc:/# certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: sszxc.net
    Domains: sszxc.net www.sszxc.net
    Expiry Date: 2020-**-** **:**:**+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/sszxc.net/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/sszxc.net/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参考资料

  1. 服务器重启后,重启 nginx 报错
  2. 通过 Certbot 安装 Let’s Encrypt 证书,来实现全站的 HTTPS 访问