zzxworld

Let’s Encrypt 免费 SSL/HTTPS 证书的申请和续期

我这个网站之前一直使用阿里云的免费 SSL 证书,每次申请后能管一年。最近证书快要到期,准备重新申请下一个年度的 SSL 证书,登录到阿里云后台发现这个功能有了些变化。免费证书名字改成了测试证书,一年的有效时长也变成了三个月,如果想要一年时长的证书,需要交费 68 元。网站本来就没收入,本着能省就省的原则,决定还是改用 Let’s Encrypt。

Let’s Encrypt 是一家国外免费的证书颁发机构,已经运营多年,稳定性令人放心。虽然证书申请后也只有三个月有效期,但支持通过程序自动化续期,体验上跟长期证书并无二致,就这点来看,阿里云还有得学。

证书申请

Let’s Encrypt 支持很多 ACME(自动证书管理环境)协议的客户端软件,官方目前推荐的是 Certbot,所以我也准备使用这个客户端。Certbot 基于 Python 语言,所以首先要准备好 Python 执行环境:

python3 -m venv ./venv
source venv/bin/activate

Linux 服务器一般都自带了 Python 执行环境,所以上面这步并不是必须的,只是我的个人软件安装洁癖,习惯了给不同的软件配置隔离的执行环境。

接下来开始用 pip 命令安装 Certbot:

pip install certbot certbot-nginx

我用的 Web 服务是 Nginx,所以还搭上了 certbot-nginx 扩展。安装好 Certbot 后,就可以开始通过命令给网站申请证书。申请适用于 Nginx 的 SSL 证书命令如下:

sudo certbot certonly --nginx

第一次执行需要完成几个交互式的选项,按提示操作即可。在操作的过程中,会根据 Nginx 中的站点配置自动列出可以申请的域名。

如果只是给特定的域名申请 SSL 证书,可以使用 -d 命令选项指定域名:

sudo certbot --nginx -d www.zzxworld.com

命令执行成功后会有如下所示的输出内容:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/www.zzxworld.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/www.zzxworld.com/privkey.pem
This certificate expires on 2024-12-22.

脚本会在域名的 Nginx 配置中自动插入证书配置,证书相关的配置示例如下:

listen 443 ssl;

ssl_certificate /etc/letsencrypt/live/v2.miparts.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/v2.miparts.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;

if ($scheme != "https") {
    return 301 https://$host$request_uri;
}

证书续期

证书续期同样是使用 certbot 命令,可以手动测试一下续期命令:

sudo certbot renew --dry-run

以上命令会根据当前服务器上已经申请的域名 SSL 证书模拟续期操作,一切无误会输出以下内容:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/www.zzxworld.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

去掉命令后的 --dry-run 参数就可以开始真正的续期操作,续期成功后,证书的有效期又能延期三个月,所以接下来只要记得每三个月登录到服务器上执行一次命令即可。

三个月操作一次虽然并没有多大负担,但能交给软件自动化执行的事情也没必要自己一直记着。结合 Linux 服务器上的 Crontab 计划任务,就能实现让证书自动无限续期:

0 0 * * 0       certbot renew --quiet --post-hook "systemctl restart nginx"

以上自动任务设置为每周执行一次续期命令,之所以按周是因为 Let’s Encrypt 的证书续期只有在过期前 30 天内才能生效,按天执行频率过高,按月的话容错率低,综合来看,按周是比较合理的。

实际使用中发现,续期命令的确存在执行失败的问题,所以稳妥起见,还是要定期人工检查一下站点证书的到期时间。比如上面的命令是每周日执行一次续签,我就在手机上设定了一个每周一检查站点证书的提醒事项,以确保自动续签失败时能及时人工处理。

4 条评论

  1. 扶苏
    然后就有个很尴尬的问题,网站的 ssl 自动更换了,cdn 那的还要手动换
    • zzxworld
      这的确是多了一步要解决的事情。
  2. 网友小宋
    目前有很多平台已经做了自动同步cdn的功能了
    • zzxworld
      还没用过 CDN,这么看来用 CDN 问题也不大了。