使用 acme.sh 申请 SSL 证书并且定期自动更新

在我们的实际项目生产过程中往往需要为部署的服务和域名配置 SSL 证书,可以采用的方法有很多种,例如可以申请阿里云的免费 SSL 证书,或者也可以使用 CloudFlare 的 SSL 服务。本文介绍了一种使用 acme.sh 脚本工具来申请 Let’s Encrypt! 免费的 SSL 证书,并能够在证书快过期时自动重新申请新证书。这样减轻了运维的负担,不需要再去记录证书的过期时间,也不需要再手动申请新证书和手动进行更新了。

一、安装 acme.sh 脚本

acme.sh 的脚本安装非常简单,只需要在终端中执行如下命令:

1
curl https://get.acme.sh | sh

(如果系统未安装 curl 工具,请先进行安装)

二、验证域名并生成证书

acme.sh 验证域名的方式一般有两种方式:HTTP 验证和 DNS 验证。

HTTP 验证的方式是需要往域名特定的 url 下面放置一个 txt 文件,用于验证你确实拥有该域名。

本文推荐的方式是使用 DNS 验证的方式,使用这种方式可以通过使用域名解析商提供的 API 自动添加 DNS 的 txt 记录来完成验证,是最简单、最快捷的方式。使用这种方式无需验证 IP,可以方便地实现 SSL 证书的自动申请和续签。

acme.sh 目前支持阿里云,CloudFlare,DNSpod,Cloudxns,Godaddy 以及 ovh 等数十种解析商的 API 自动集成,本文以阿里云和 CloudFlare 为例来介绍如何来验证域名。

1. 阿里云(Aliyun)

如果你的域名解析商是阿里云,那么你可以采用这种方式来验证域名。

首先,你需要为阿里云账号创建一个子账号来为更新 DNS 解析记录的操作申请一个 API Key,访问阿里云 RAM 访问控制,创建一个用户。

我们可以创建一个 acme 用户:

在分配权限时,分配 AliyunDNSFullAccess 的权限:

之后会分配 Key 和 Secret,这部分数据需要妥善保存。

可以将 Key 和 Secret 放到终端的环境变量中:

1
vi ~/.bashrc

把 Key 和 Secret 添加到文件末尾:

1
2
export Ali_Key="xxxxxx"
export Ali_Secret="xxxxxx"

使环境变量生效:

1
source ~/.bashrc

下面执行如下命令来验证域名(以 example.com 域名为例)并生成证书:

1
acme.sh --issue --dns dns_ali -d example.com -d *.example.com

执行后的结果:

1
2
3
4
[Fri Oct 23 13:21:09 CST 2020] Your cert is in  /root/.acme.sh/ example.com/ example.com.cer 
[Fri Oct 23 13:21:09 CST 2020] Your cert key is in /root/.acme.sh/ example.com/ example.com.key
[Fri Oct 23 13:21:09 CST 2020] The intermediate CA cert is in /root/.acme.sh/example.com/ca.cer
[Fri Oct 23 13:21:09 CST 2020] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer

你可以将 nginx 等 SSL 配置指向该目录,也可以使用如下命令,将证书安装到指定目录:

1
2
3
4
5
acme.sh --issue --dns dns_ali -d example.com -d *.example.com\
--installcert\
--key-file /etc/nginx/cert.d/example.com.key\
--fullchain-file /etc/nginx/cert.d/example.com.pem\
--reloadcmd "nginx -s reload"

2. CloudFlare

如果你的域名解析商是 CloudFlare,那么你可以采用这种方式来验证域名。

首先,你需要申请一个 CloudFlare 的 API KEY,打开 https://dash.cloudflare.com/profile/api-tokens ,Create Token:

按后续提示操作,生成具有更新 DNS 权限的 API Key。

可以将 CloudFlare 登录邮箱和 Key 放到终端的环境变量中:

1
vi ~/.bashrc

把 Key 和 Secret 添加到文件末尾:

1
2
export CF_Email="xxxxxx"
export CF_Key="xxxxxx"

使环境变量生效:

1
source ~/.bashrc

下面执行如下命令来验证域名(以 example.com 域名为例)并生成证书:

1
acme.sh --issue --dns dns_cf -d example.com -d *.example.com

执行后的结果:

1
2
3
4
[Fri Oct 23 13:21:09 CST 2020] Your cert is in  /root/.acme.sh/ example.com/ example.com.cer 
[Fri Oct 23 13:21:09 CST 2020] Your cert key is in /root/.acme.sh/ example.com/ example.com.key
[Fri Oct 23 13:21:09 CST 2020] The intermediate CA cert is in /root/.acme.sh/example.com/ca.cer
[Fri Oct 23 13:21:09 CST 2020] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer

你可以将 nginx 等 SSL 配置指向该目录,也可以使用如下命令,将证书安装到指定目录:

1
2
3
4
5
acme.sh --issue --dns dns_cf -d example.com -d *.example.com\
--installcert\
--key-file /etc/nginx/cert.d/example.com.key\
--fullchain-file /etc/nginx/cert.d/example.com.pem\
--reloadcmd "nginx -s reload"

二、自动续期

执行完上述命令之后,脚本会在 cron 定时任务中加上一个定时任务,用于定期检查证书是否过期,并且自动更新 SSL 证书。使用如下命令可以查看该定时任务:

1
crontab -l

三、更新 acme.sh

目前由于 acme 协议和 Let’s Encrypt! 会时常更新,因此需要对 acme.sh 脚本进行更新:

1
acme.sh --upgrade

也可以开启自动更新:

1
acme.sh --upgrade --auto-upgrade

关闭自动更新:

1
acme.sh --upgrade --auto-upgrade 0

本文的版权归作者 罗远航 所有,采用 Attribution-NonCommercial 3.0 License。任何人可以进行转载、分享,但不可在未经允许的情况下用于商业用途;转载请注明出处。感谢配合!