使用acme.sh给Web网站自动安装免费的SSL证书并自动更新,轻松实现HTTPS
本文最后更新于 2024年9月21日 凌晨
出于安全考虑,现在大部分的网站都已经配置了SSL证书,直观的感觉就是现在大部分的网站都是HTTPS,而不是HTTP了。甚至,Chrome 从90版本开始,就已经是默认请求HTTPS:
那么,我们个人在部署网站的时候,如何部署SSL,快速实现HTTPS呢?方法很多,个人觉得,使用acme.sh是一个很不错的工具。
acme.sh
acme.sh是一个用纯Shell(Unix shell语言)写成的ACME协议客户端,作为对比,acme协议是Let’s Encrypt和其他CA机构使用的一种网络交互协议,用于自动验证网站/域名并颁发SSL/TLS证书。
acme.sh就是利用这个acme协议,使用单一的Shell脚本自动为网站颁发和续订SSL证书。主要特点和功能包括:
- 纯Shell语言实现,无其他依赖,很容易安装和使用。
- 支持多种操作系统,如Linux、macOS、Windows(需要Cygwin)等。
- 支持www模式、独立模式、DNS模式来验证域名。可以自动通过API完成DNS记录验证。
- 可以为单域名或泛域名(通配符)颁发证书。支持SAN证书。
- 可以直接安装颁发的证书到Nginx或Apache服务器。
- 默认每60天自动检查并自动续订证书。
- 支持ECC加密算法颁发的证书。
上手非常简单,如果你的Linux命令熟练几分钟即可上手使用。
目前支持的CA机构和CA机构支持的功能:
CA | 最大有效期(日) | ECC加密 | 域名数量限制 | 泛域名 | IPv4 | IPv6 | 过期日 | IDN |
---|---|---|---|---|---|---|---|---|
Let’s Encrypt | 90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
ZeroSSL | 90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
90 | 支持 | 100 | 支持 | 不支持 | 不支持 | 支持 | 不支持 | |
Buypass | 180 | 支持 | 5 | 付费 | 不支持 | 不支持 | 不支持 | 支持 |
SSL.com | 90 | 支持 | 2 | 付费 | 不支持 | 不支持 | 不支持 | 支持 |
acme.sh 主要有部署SSL的方案非常多,不过我个人主要使用两种方案,也是我推荐的两种方案:
- Web服务器验证: 使用Nginx验证网站的归属,实现证书签发验证。
- DNS API验证: 使用DNS厂商的API,自动校验域名归属,实现证书签发和续签。
如何安装
如何安装acme.sh呢?一条命令即可:
1 |
|
国内服务器如果无法访问,可以克隆仓库后手动安装:
1 |
|
为什么最好使用ZeroSSL的账号邮箱呢?很早之前,ZeroSSL就买了
acme.sh
这个网站,所以,后来amce.sh切换默认的CA为ZeroSSL也是很正常的啦。而ZeroSSL申请SSL,需要预留邮箱。
安装成功:
之后,我们使用acme.sh -v
,就可以看到acme.sh的版本号:
如果acme.sh没有添加到环境变量内,可以进行手动添加:
常用命令
在教程开始之前,我们看看acme.sh的基础命令:
1 |
|
而查看帮助内,比较常用的是:
1 |
|
一些情况下,acme.sh可能会报错,这个时候,优先尝试升级acme.sh:
1 |
|
其次是默认使用ZeroSSL,如果你想切换默认的CA,可以:
1 |
|
除了默认的letsencrypt(Let’s Encrypt)和zerossl(ZeroSSL),默认配置下,还支持的CA选项:buypass(Buypass)、ssl.com(SSL.com)和google(Google Public CA)。
同时,如果你申请了很多域名,但是其中有的域名已经不再使用,需要进行删除操作时,可以使用命令:
1 |
|
接下来,我们看看如何使用acme.sh申请SSL证书。
支持创作
书写文章不易,如果热心的小伙伴,想支持创作,可以加入我们的「爱发电」电圈(还可以解锁远程协助、好友位😃):
当然,也欢迎在B站或YouTube上关注我们:
更多:
ZeroSSL
acme.sh在3.0开始,默认使用ZeroSSL:https://zerossl.com/
其实和原本的Let’s Encrypt差不多,ZeroSSL有一个可视化的界面,还是很不错的,可以直观查看SSL是否续期成功;但是有点尴尬的是,我绑定了多个通配域名后,ZeroSSL的控制台上,还是空空如也,可能ZeroSSL的控制台目前还不支持acme.sh的通配符展示(也可能是我部署的时候,ZeroSSL的服务器宕机了):
不过,不影响我们的使用,你还是可以用acme.sh --list
看看Linux服务器上SSL证书的续期情况。
如果你在使用acme.sh的时候,在已经有ZerorSSL的情况下,可以直接进行绑定:
1 |
|
当然,你也可以直接使用ZeroSSL的EAB:
1 |
|
其中的kid
和key
可以在ZeroSSL的这里进行获取:
如果你不想使用ZeroSSL,可以切换为letsencrypt
。
方式对比
acme.sh支持多种方法进行部署,不过常用的是两种:
- HTTP验证: 通过在Web服务器上创建临时文件,让ACME服务器验证域名的控制权。acme.sh可以自动配置常见的Web服务器,如Apache和Nginx,以便进行HTTP验证。我们也可以使用acme.sh提供的命令来生成临时文件并在验证完成后进行清理。
- DNS验证: 通过在DNS服务器上添加相应的DNS TXT记录来验证域名所有权。acme.sh官方提供了多个DNS服务提供商的支持,包括Cloudflare、GoDaddy、Aliyun等。其他第三方DNS也可以根据ACME协议进行对接,不过大部分的DNS服务厂商,其实acme.sh都已经支持了。
两个方法都是很快速的方法,从结果上出发,最的区别就是DNS验证可以签署通配域名,也就是签署顶级二级域名后,其顶级二级域名分割出的三级域名都可以使用这个证书。
举个例子: 你为顶级二级域名example.com
签署通配域名*.example.com
,那么a.example.com
和b.example.com
都可以使用这个通配域名证书。但是,使用acme.sh签署通配域名证书,只能使用DNS验证的方式进行签署。
接下来,我们就来分别演示。
HTTP验证签署
acme.sh 其实可以自动HTTP验证。也就是你的Web服务器已经配置的情况下,你可以选择acme.sh自动修改Web配置并验证;也可以手动自动配置,并使用acme.sh进行配置的验证。
本次使用Nginx服务器为例,Apache其实也差不多。
自动配置签署
自动部署配置,其实就是自动配置Web服务器(Nginx、Apache)的配置,创建验证文件;在验证成功后,下载并配置好SSL证书,需要手动配置HTTPS。
首先,我们需要确保Nginx已经配置到环境变量内:
1 |
|
在配置之前,确保Nginx当前的配置是可用的状态:
1 |
|
按道理,就可以使用官方的命令进行安装:
1 |
|
配置完成:
配置的原理是怎么样呢?
首先,acme.sh会检测Nginx的配置文件地址。如果你的Nginx使用的是主config文件,引入子config(也就是:include /www/wwwConf/*.conf
这样的形式)也是支持的;根据你指定的域名,找到具体的server
配置片段所在的文件,将其备份。
之后,修改server
配置片段,主要的修改内容就是后续我们手动的配置;修改配置后,acme.sh会使用Nginx的nginx -t
检测配置的合法性,如果不合法,那么直接恢复备份终止脚本。
最后,在server
修改完成,并和CA校验成功后;签署SSL证书并还原Nginx备份。之后如果是acme.sh的续签,也是重新运行此过程。
graph TD
style A fill:#f9d644,stroke:#333,stroke-width:4px
style B fill:#99ccff,stroke:#333,stroke-width:4px
style C fill:#90ee90,stroke:#333,stroke-width:4px
style D fill:#ffcccc,stroke:#333,stroke-width:4px
style E fill:#ffff99,stroke:#333,stroke-width:4px
style F fill:#c0c0c0,stroke:#333,stroke-width:4px
A[临时修改<br>Nginx配置] -- "申请" --> B[向CA机构<br>申请证书]
B --> C[生成证书]
C --> D[重置Nginx<br>配置为原始版本]
D --> E[证书生成完成]
E --> F[定期证书续期检查]
F --> |证书尚未到期| E
F --> |证书即将到期| A
那么如果你不想让acme.sh自动配置呢?我们可以自己配置。
手动配置签署
手动配置的灵活性更高;自动配置签署和手动配置签署二选一就可以了。
手动配置,就是在Nginx上配置一个目录,使其acme.sh在Linux的服务器内写入CA机构下发的验证文件,通过Http可以访问到。
首先,在Linux服务器上创建一个目录:
1 |
|
并且在Nginx上进行配置:
1 |
|
重载Nginx的配置,使用acme.sh即可完成配置部署:
1 |
|
解释一下:
- -d example.com: 指定主域名为example.com。
- -d www.example.com: 指定附加域名为www.example.com,这将成为同一个证书的 Subject Alternative Name。
- -w /www/acme: 指定校验域名所有权的网站根目录为/www/acme。acme.sh会在此目录下生成临时文件用来向CA验证域名所有权。
CA机构的验证API正常的情况下,签署的过程是很丝滑的:
需要注意的是,我们设置的/.well-known/acme-challenge/
目录配置不要删除,否则可能影响后续的SSL续签。
部署SSL证书
acme.sh配置已经部署完成了:
我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:
1 |
|
操作的效果:
解释一下:
命令参数:
- –install-cert:安装 SSL 证书。
- -d www.example.com: 指定要安装证书的域名。
- –key-file: 指定私钥文件的路径。
- –fullchain-file: 指定包含证书链的 PEM 文件的路径。
- –reloadcmd: 指定在安装/更新证书后重新加载Web服务器的命令。
之后就是设置Nginx的HTTPS了,这里不再赘述。
DNS验证签署
acme.sh还可以使用DNS验证签署的方式,支持通配域名,配合DNS厂商的API,也可以实现自动续期:
sequenceDiagram
participant U as 用户服务器
participant A as acme.sh
participant DP as DNS提供商
participant CA as 证书机构
U->A: 签发证书
A->DP: 创建TXT记录
DP->A: 证书签发完成
A->CA: 请求签名
CA->A: 返回签名
A->U: TXT生效等待
U-->A: 续订证书
A->DP: 更新TXT记录
DP->A: TXT记录已更新
A->CA: 请求续订签名
CA->A: 返回续订签名
A-->U: 更新证书
从流程图就可以看出来,我们需要DNS添加TXT验证。 如果是自己添加DNS的TXT的验证,岂不是和以往差不多么?没错,acme.sh就是可以通过DNS厂商的API,自动添加TXT验证,在验证成功后,自动删除添加的TXT验证;同理,续期也是一样的。
DNS API KEY
acme.sh 需要使用DNS厂商的API,添加TXT记录地址,帮助CA签发机构验证我们对域名的所有权。而acme.sh操作DNS厂商的API,就需要API密钥鉴权。
acme.sh已经适配了多家DNS厂商的API,比如: Cloudflare,、DNSPod(腾讯)、Cloudxns, Godadd等等。我们就以DNSpod为例,看看如何操作。
DNSpod在acme.sh的别名是:dns_dp
,其他厂商的别名和支持,可以查看:
如果你所使用的DNS,不在acme.sh的支持列表内,你可以尝试手动适配: https://github.com/acmesh-official/acme.sh/wiki/DNS-manual-mode
登录DNSpod的后台地址:https://console.dnspod.cn/
选择API密钥管理:
之后,我们创建一个密钥:
创建好的ID和Token密钥:
环境变量
acme.sh会从环境变量内,读取所需要用到的DNS API地址。你可以直接临时使用:
1 |
|
只要你在后续使用acme.sh的--dns dns_dp
前,没有重载环境变量,那么acme.sh会把这个环境变量写入~/.acme.sh/account.conf
内:
当然,我会直接写到环境变量内,其实都一样:
签署证书
我们使用acme.sh进行签署和验证:
1 |
|
一点点小的报错“红字”是没有关系的;如果没什么问题,片刻的等待后,就可以得到证书内容:
签署的过程是很丝滑的。
部署SSL证书
我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:
1 |
|
操作的效果:
之后就是设置Nginx的HTTPS了,这里不再赘述。最后网站的效果:
END
好啦,本次的教程就到这里啦。其实acme.sh的原理是挺简单的,对DNS的API和CA接口进行操作;省去了用户自己造“轮子”的时间和精力。
其实一开始别人和我推荐acme.sh的时候,我其实是比较反感的,总觉得,脚本修改网站配置或者给出DNS的API Key,也不安全。但是可以直接用别人造好的“轮子”是真的方便,而且本身是开源项目,其实及时更新,一般也没什么问题。