出于安全考虑,现在大部分的网站都已经配置了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,自动校验域名归属,实现证书签发和续签。
操作前提
本次的操作前提是什么呢?很简单:
- 一台服务器并部署Nginx服务;推荐使用腾讯云轻量应用服务器、腾讯云CVM服务器,轻松部署Nginx服务、搭建Web。
- 域名和DNS服务器;比如:腾讯云的DNSPod、Cloudflare。
注意,目前 acme.sh 安装的证书,是存放在服务器上,如果是使用CDN;需要自行考虑证书的同步问题。或者直接使用腾讯云的下一代CDN: EdgeOne。有机会,我们介绍EdgeOne的方法。
如何安装
如何安装 acme.sh 呢?一条命令即可:
代码语言:bash复制curl https://get.acme.sh | sh -s email=my@example.com # 换成自己的邮箱(最好是ZeroSSL账号)
国内服务器如果无法访问,可以克隆仓库后手动安装:
代码语言:bash复制# 克隆仓库
git clone https://github.com/acmesh-official/acme.sh.git
# 进入仓库内
cd ./acme.sh
# 运行脚本
./acme.sh --install -m my@example.com # 换成自己的邮箱(最好是ZeroSSL账号)
为什么最好使用 ZeroSSL 的账号邮箱呢?很早之前,ZeroSSL 就买了
acme.sh
这个网站,所以,后来 amce.sh 切换默认的 CA 为 ZeroSSL 也是很正常的啦。而 ZeroSSL 申请 SSL ,需要预留邮箱。
在腾讯云的香港服务器安装成功:
之后,我们使用acme.sh -v
,就可以看到 acme.sh 的版本号:
如果 acme.sh 没有添加到环境变量内,可以进行手动添加:
常用命令
在教程开始之前,我们看看 acme.sh 的基础命令:
代码语言:bash复制acme.sh -h
而查看帮助内,比较常用的是:
代码语言:bash复制acme.sh --list
一些情况下,acme.sh 可能会报错,这个时候,优先尝试升级 acme.sh:
代码语言:bash复制# 升级acme.sh
acme.sh --upgrade
# 开启acme.sh的自动升级
acme.sh --upgrade --auto-upgrade
# 关闭acme.sh的自动升级
acme.sh --upgrade --auto-upgrade 0
其次是默认使用 ZeroSSL,如果你想切换默认的 CA ,可以:
代码语言:bash复制# 切换默认的CA机构为 letsencrypt
acme.sh --set-default-ca --server letsencrypt
除了默认的letsencrypt(Let’s Encrypt)和zerossl(ZeroSSL),默认配置下,还支持的CA选项:buypass(Buypass)、ssl.com(SSL.com)和google(Google Public CA)。
同时,如果你申请了很多域名,但是其中有的域名已经不再使用,需要进行删除操作时,可以使用命令:
代码语言:bash复制acme.sh --remove -d example.com
接下来,我们看看如何使用acme.sh申请SSL证书。
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的情况下,可以直接进行绑定:
代码语言:bash复制acme.sh --register-account -m 「ZeroSSL邮箱」 --server zerossl
当然,你也可以直接使用ZeroSSL的EAB:
代码语言:bash复制acme.sh --register-account --server zerossl
--eab-kid "你账号的kid"
--eab-hmac-key "你账号的key"
其中的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已经配置到环境变量内:
代码语言:nginx复制# 查看Nginx的版本
nginx -v
在配置之前,确保Nginx当前的配置是可用的状态:
代码语言:bash复制$ nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful
按道理,就可以使用官方的命令进行安装:
代码语言:bash复制acme.sh --issue -d example.com --nginx
配置完成:
配置的原理是怎么样呢?
首先,acme.sh会检测Nginx的配置文件地址。如果你的Nginx使用的是主config文件,引入子config(也就是:include /www/wwwConf/*.conf
这样的形式)也是支持的;根据你指定的域名,找到具体的server
配置片段所在的文件,将其备份。
之后,修改server
配置片段,主要的修改内容就是后续我们手动的配置;修改配置后,acme.sh会使用Nginx的nginx -t
检测配置的合法性,如果不合法,那么直接恢复备份终止脚本。
最后,在server
修改完成,并和CA校验成功后;签署SSL证书并还原Nginx备份。之后如果是acme.sh的续签,也是重新运行此过程。
那么如果你不想让acme.sh自动配置呢?我们可以自己配置。
手动配置签署
手动配置的灵活性更高;自动配置签署和手动配置签署二选一就可以了。
手动配置,就是在Nginx上配置一个目录,使其acme.sh在Linux的服务器内写入CA机构下发的验证文件,通过Http可以访问到。
首先,在Linux服务器上创建一个目录:
代码语言:bash复制# 创建目录,用存放acme.sh验证文件
mkdir -p /www/acme/.well-known/acme-challenge
# 授权给nginx所在的用户
chown -R www:www /www/acme
并且在Nginx上进行配置:
代码语言:nginx复制location /.well-known/acme-challenge/ {
alias /www/acme/.well-known/acme-challenge/;
}
重载Nginx的配置,使用acme.sh即可完成配置部署:
代码语言:nginx复制# Nginx 重载配置
nginx -s reload
# 使用acme.sh验证配置
acme.sh --issue -d example.com -d www.example.com -w /www/acme
解释一下:
- -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,使用命令:
代码语言:bash复制acme.sh --install-cert -d www.example.com
--key-file /www/ssl/www.example.com.key
--fullchain-file /www/ssl/www.example.com.pem
--reloadcmd "systemctl reload nginx"
操作的效果:
解释一下:
命令参数:
- --install-cert:安装 SSL 证书。
- -d www.example.com: 指定要安装证书的域名。
- --key-file: 指定私钥文件的路径。
- --fullchain-file: 指定包含证书链的 PEM 文件的路径。
- --reloadcmd: 指定在安装/更新证书后重新加载Web服务器的命令。
之后就是设置Nginx的HTTPS了,这里不再赘述。
DNS验证签署
acme.sh还可以使用DNS验证签署的方式,支持通配域名,配合DNS厂商的API,也可以实现自动续期:
代码语言:mermaid复制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
,其他厂商的别名和支持,可以查看:
- acme.sh 官方文档: DNS官方支持列表以及API KEY获取
- acme.sh 官方文档: DNS官方支持列表以及API KEY获取(补充)
如果你所使用的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地址。你可以直接临时使用:
代码语言:bash复制export DP_Id="<id>"
export DP_Key="<key>"
只要你在后续使用acme.sh的--dns dns_dp
前,没有重载环境变量,那么acme.sh会把这个环境变量写入~/.acme.sh/account.conf
内:
当然,我会直接写到环境变量内,其实都一样:
签署证书
我们使用acme.sh进行签署和验证:
代码语言:bash复制acme.sh --dns dns_dp --issue -d "example.com" -d "*.example.com" --server zerossl
一点点小的报错“红字”是没有关系的;如果没什么问题,片刻的等待后,就可以得到证书内容:
签署的过程是很丝滑的。
部署SSL证书
我们需要把SSL证书安装到网站的SSL目录内,方便Nginx的配置内开启SSL,使用命令:
代码语言:bash复制acme.sh --install-cert -d www.example.com
--key-file /www/ssl/www.example.com.key
--fullchain-file /www/ssl/www.example.com.pem
--reloadcmd "systemctl reload nginx"
操作的效果:
之后就是设置Nginx的HTTPS了,这里不再赘述。最后网站的效果:
END
好啦,本次的教程就到这里啦。其实acme.sh的原理是挺简单的,对DNS的API和CA接口进行操作;省去了用户自己造“轮子”的时间和精力。
其实一开始别人和我推荐 acme.sh 的时候,我其实是比较反感的,总觉得,脚本修改网站配置或者给出DNS的API Key,也不安全。但是可以直接用别人造好的“轮子”是真的方便,而且本身是开源项目,其实及时更新,一般也没什么问题。