acme.sh 使用文档
ACME是"Automatic Certificate Management Environment”(自动证书管理环境)的缩写。ACME是一种用于自动化管理和获取SSL/TLS证书的协议。ACME协议由Internet工程任务组(IETF)定义,并由Let’s Encrypt等证颁发机构广泛采用。
ACME提供了一种标准化的方式,使能够自动请求、验证和获取证书,而无需人工干预。完成标准化获取证书流程需要ACME客户端与ACME服务器端进行通信。常见的ACME客户端有acme.sh、certbot等。
acme.sh的github地址:https://github.com/acmesh-official/acme.sh
安装
-
在线安装
使用如下命令,邮箱设置为你接受通知的邮箱号
curl https://get.acme.sh | sh -s email=my@example.com
或者
wget -O - https://get.acme.sh | sh -s email=my@example.com
-
git安装
git clone https://github.com/acmesh-official/acme.sh.git cd ./acme.sh ./acme.sh --install -m my@example.com
安装命令将执行3个操作:
1.创建并复制acme.sh
到您的主目录 ( $HOME
): ~/.acme.sh/
。所有证书也将放置在此文件夹中。
2.创建别名:acme.sh=~/.acme.sh/acme.sh
.
3.创建每日 cron 作业来检查并更新证书(如果需要)。
安装完成后重启终端生效,使用acme.sh -v
获取到版本信息即安装成功
$ acme.sh -v
https://github.com/acmesh-official/acme.sh
v3.0.7
安装成功后,Windows的默认存储目录在C:\Users\用户名\.acme.sh
,Linux的默认存储目录在/root/.acme.sh
注册
使用如下命令注册ACME客户端:
acme.sh --register-account --server https://acme.certcloud.cn/acme/directory --eab-kid J9Lf****** --eab-hmac-key MD8C******
- –register-account: 表示这是注册账户的命令
- –server:指定ACME服务端地址
- –eab-kid、–eab-hmac-key: eab是ACME标准协议中用于绑定第三方账户的参数,可通过Certcloud控制台-自动化-ACME-设置处获取
命令行中打印如下结果即表示注册账户成功:
$ acme.sh --register-account --server https://acme.certcloud.cn/acme/directory --eab-kid WDq1JnEoJbbEq6B55iY0ueeLaQTYCtMjvzj9241tnYm --eab-hmac-key WD4CAQACCQDZchZ62AbEpwIDAQABArhs08yrghyoAQIFAN4As18CBQD6mnu5AgQ2c/+LAgUAvR+ViQIEISwZ7z==
[Tue Dec 5 17:06:49 2023] Registering account: https://acme.cmc.test/acme/directory
[Tue Dec 5 17:06:52 2023] Already registered
[Tue Dec 5 17:06:53 2023] ACCOUNT_THUMBPRINT='yph9FN9ANi47lL327cCozaqUooVF5Kjyb_t_QwEQG48'
手动签发证书
acme.sh --issue --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --cert-home /root/test --domain qeqwe.a.online --server https://acme.certcloud.cn/acme/directory --dnssleep 20 --keylength 2048
-
–issue: 表示这是一个签发证书的命令
-
–dns: 表示使用DNS验证方式验证您拥有域名的控制权
-
–yes-I-know-dns-manual-mode-enough-go-ahead-please: 这是手动模式下的一个参数,表明您确实了解并足够了解手动模式的操作
-
–cert-home:证书存放目录
-
–domain : 要签发证书的域名
-
–server: 指定ACME服务端地址
-
–dnssleep :睡眠一定时间(秒)等待DNS传播
上述命令通过手动配置dns验证,验证通过后最终会在当前命令执行的目录下载对应的证书。
不推荐采用上述方式进行签发部署证书,这意味着您每次在证书快要过期时都要手动执行该命令进行验证签发证书。我们可以使用dns插件的方式实现自动验证并签发证书, 不同的DNS解析服务提供商有不同的配置。请根据您的域名所在解析服务器相对应的插件命令执行。
自动签发证书
注:本节中dns插件密钥配置仅用于DV证书,对于OV或EV证书配置任意插件如–dns dns_tencent,而不用配置其环境变量,因为通过预审核后acme.sh会跳过验证签发证书
腾讯云
如果您的域名在在腾讯云,使用类似的命令如下:
acme.sh --issue --dns dns_tencent --cert-home /root/test -d example.com -d *.example.com -d a.com --server https://acme.certcloud.cn/acme/directory --dnssleep 20 --keylength 2048
- –dns dns_tencent:使用腾讯云dns插件,需要配置环境变量
export Tencent_SecretId="<id>"
export Tencent_SecretKey="<key>"
有两种方式获取腾讯云的SecretId 和 SecretKey,下面进行说明:
方式一:使用主账号API密钥
您可以直接跳转腾讯云API密钥管理处创建密钥,也可在腾讯云官网搜索框搜索访问管理
,选择API密钥管理
并点击新建密钥
,如下图所示:
上述方式的密钥权限较大,请谨慎使用
方式二:使用子账号密钥
仍然通过上述方式进入访问管理
,策略
->新建自定义策略
选择按策略语法创建
->空白模板
,填写基本信息,并将策略语法修改为以下内容,并点击完成
创建
{
"statement": [
{
"action": [
"dnspod:DescribeRecordFilterList",
"dnspod:DescribeRecordList",
"dnspod:CreateRecord",
"dnspod:DeleteRecord"
],
"effect": "allow",
"resource": [
"*"
]
}
],
"version": "2.0"
}
接着选择左侧用户
->用户列表
,并点击新建用户
选择快速创建
,填写用户信息,并选择编程访问
创建用户成功界面能获取到默认创建的SecretId 和 SecretKey,或者从用户列表
进入用户详情,点击新建密钥
获取到SecretId 和 SecretKey后你还需要为新创建的子账户进行授权
,将刚刚创建的策略关联到子账户
在获取SecretId 和 SecretKey时,应当清楚密钥的权限范围
dnspod
腾讯云已经收购dnspod,如果你已登录腾讯云平台,跳转到dnspod是免登录的。腾讯云平台购买的域名能在dnspod官网 中查询到,因此你也可以使用dnspod的密钥进行授权自动验证域名所有权。 如果您的域名在dnspod解析,使用类似的命令如下:
acme.sh --issue --dns dns_dp --cert-home /root/test -d example.com -d *.example.com -d a.com --server https://acme.certcloud.cn/acme/directory --dnssleep 20 --keylength 2048
需要配置环境变量
export DP_Id="<id>"
export DP_Key="<key>"
登录dnspod官网后点击头像的API密钥
,你可以查看在到腾讯云创建的密钥,详细流程参考上一模块,我们接着创建DNSPod Token
选择 DNSPod Token
,就到了 dnspod 的 token 生成页面,点击创建密钥,获取到 ID 和 token并设置到对应的环境变量DP_Id
和DP_Key
阿里云
如果您的域名在阿里云DNS解析,使用类似的命令如下:
./acme.sh --issue --dns dns_ali -d example.com -d *.example.com -d a.com --server https://acme.certcloud.cn/acme/directory --dnssleep 20 --keylength 2048
需要配置环境变量
export Ali_Key="<key>"
export Ali_Secret="<secret>"
获取阿里云的key和secret过程为:
-
登录RAM控制台。
-
在左侧导航栏,选择身份管理 > 用户,创建用户会自动生成一对key和secret。
-
在用户页面,单击目标RAM用户名称。
-
在用户AccessKey区域,单击创建AccessKey。
-
根据界面提示完成安全验证。
-
在创建AccessKey对话框,查看AccessKey ID和AccessKey Secret。您可以单击下载CSV文件,下载AccessKey信息。或单击复制,复制AccessKey信息。
-
单击确定。
创建过程如下图所示:
在用户下创建密钥后还需要给用户进行AliyunDNSFullAccess
授权,如下图所示:
上述过程使用了系统策略AliyunDNSFullAccess
,你可以自定义策略,控制授权的粒度。
Amazon Route53
您的域名在AWS Route53解析,可以使用类似如下命令:
acme.sh --issue --dns dns_aws -d example.com -d *.example.com -d a.com --server https://acme.certcloud.cn/acme/directory --dnssleep 20 --keylength 2048
如果出现AWS Route53 rate exceeded
错误,可以在 api 请求之间添加睡眠时间,避免AWS的限速问题:
export AWS_DNS_SLOWRATE=1
需要配置环境变量如下:
export AWS_ACCESS_KEY_ID="<key id>"
export AWS_SECRET_ACCESS_KEY="<secret>"
下面用国内AWS获取id和secret进行说明,国外AWS也是类似操作。过程如下:
- 点击跳转国内AWS IAM控制台,或搜索服务
IAM
进入 - 在左侧导航栏,选择访问管理 > 用户
- 创建用户并点击用户名进入或直接点击用户名进入
- 选择安全凭证 > 访问密钥
- 创建访问密钥
创建过程参考下列图例:
此时密钥还不能正常使用,还需要给密钥所在用户授权。在左侧导航栏选择访问管理 > 策略,点击创建策略
,如下图所示:
策略编辑器选择JSON,策略内容为:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:GetHostedZone",
"route53:ListHostedZones",
"route53:ListHostedZonesByName",
"route53:GetHostedZoneCount",
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "*"
}
]
}
如下图所示:
接着下一步输出策略名称和策略描述,最后点击创建策略
。
创建策略成功后我们继续给用户添加权限,在左侧导航栏选择访问管理 > 用户,选择刚刚创建密钥的用户进入详情界面,点击添加权限,再选择直接附加策略,勾选我们刚刚创建的策略即可。
用户详情界面的策略列表显示我们刚刚新增的策略即配置成功。
对于非中国区域的AWS获取的密钥已经能够正常使用,使用中国区的AWS密钥签发证书会出现下面的错误
[Thu Dec 14 19:50:06 2023] Response error:<?xml version="1.0"?>
<ErrorResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/"><Error><Type>Sender</Type><Code>InvalidClientTokenId</Code><Message>The security token included in the request is invalid.</Message></Error><RequestId>eeee-dddd-cccc-bbbb-aaaa</ErrorResponse>
要使用中国区AWS的密钥,需要修改脚本中的AWS_HOST
和Region
参数:
Windows对应的默认安装路径为C:\Users\用户名\.acme.sh\dnsapi\dns_aws.sh
,
Linux对应的默认安装路径为/root/.acme.sh/dnsapi/dns_aws.sh
,
修改dns_aws.sh
文件中12行的AWS_HOST
为api.route53.cn
(原始值为api.route53.cn),修改dns_aws.sh
文件中302行的Region
为cn-northwest-1
(原始值为us-east-1),修改完成保存后即能正确签发证书。详情请见2722 Issues
其他
acme.sh直接支持150多个DNS API,如果您的域名所在DNS解析不在上述的说明中,请参考acme.sh文档dnsapi。如果你的域名所在DNS解析不在acme.sh的支持列表,请参考使用自定义API。
自动部署和更新证书
完成申请后你可以将证书配置到您的网站中,证书的手动部署这里不进行详细说明。以 Nginx 为例,示例如下:
server {
listen 443 ssl http2;
server_name example.com;
# 请替换为证书实际路径
ssl_certificate /root/.acme.sh/example.com/fullchain.cer;
ssl_certificate_key /root/.acme.sh/example.com/example.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
root /nginx/www/html;
}
}
回顾上述的流程,我们已能够自动签发证书,并编写了对应dns服务商的证书签发命令。例如dnspod对应的命令:
acme.sh --issue --dns dns_dp --cert-home /root/test -d yyy.aaa.site --server https://acme.cmc.test/acme/directory --dnssleep 20 --keylength 2048
下面就以Nginx为例,来了解acme.sh如何安装证书,命令如下:
acme.sh --installcert -d yyy.aaa.site --key-file /mycertify/ssl/msh.com.key --fullchain-file /mycertify/ssl/msh.com.cer --reloadcmd "/usr/local/nginx/sbin/nginx -s reload"
-
–installcert: 安装证书命令
-
-d yyy.aaa.site:会读取对应域名配置
-
–key-file:将证书私钥拷贝到该参数指定的路径
-
–fullchain-file:将证书链拷贝到该参数指定的路径
-
–reloadcmd:指定证书拷贝到对应目录后执行的命令,
/usr/local/nginx/sbin/nginx -s reload
这里是重新加载nginx配置上述安装证书命令如果不指定
--cert-home
会从默认的存储读取域名目录下的证书文件拷贝到--key-file
和--fullchain-file
指定的路径,最终执行reloadcmd参数中的命令,下图只是简单执行了
ls
命令,根据实际情况替换为重新加载证书的命令
acme.sh在安装时linux会创建每日cron任务,windows创建任务计划程序,每日定时检查证书的有效时间,在到期前自动更新证书,执行acme.sh --list
命令只查找到了默认目录下的两个证书,如下图所示:
acme.sh并没有找到我们指定了--cert-home
的证书,因此为了不影响自动续期,建议不使用该参数。上图中说明了证书的创建时间、续期时间等,第一张证书因为签发失败因此没有该证书的相关时间描述。
测试
①签发一张证书
$ acme.sh --issue --dns dns_dp --domain qqq.ldlb.site --server https://acme.cmc.test/acme/directory --dnssleep 20 --keylength 2048
assertion "bc_ctl.arg_max >= LINE_MAX" failed: file "xargs.c", line 511, function: main
[Fri Dec 15 10:13:26 2023] Using CA: https://acme.cmc.test/acme/directory
[Fri Dec 15 10:13:27 2023] Creating domain key
[Fri Dec 15 10:13:28 2023] The domain key is here: /c/Users/xc/.acme.sh/qqq.ldlb.site/qqq.ldlb.site.key
[Fri Dec 15 10:13:28 2023] Single domain='qqq.ldlb.site'
[Fri Dec 15 10:13:29 2023] Getting domain auth token for each domain
[Fri Dec 15 10:13:39 2023] Getting webroot for domain='qqq.ldlb.site'
[Fri Dec 15 10:13:41 2023] Adding txt value: pORPIsBk1hTNFUHYwsm0YBT-4vM8BwBcYgkwIdvBdgQ for domain: _acme-challenge.qqq.ldlb.site
[Fri Dec 15 10:13:44 2023] Adding record
[Fri Dec 15 10:13:45 2023] The txt record is added: Success.
[Fri Dec 15 10:13:45 2023] Sleep 20 seconds for the txt records to take effect
[Fri Dec 15 10:14:08 2023] Verifying: qqq.ldlb.site
[Fri Dec 15 10:14:12 2023] Pending, The CA is processing your order, please just wait. (1/30)
[Fri Dec 15 10:14:18 2023] Processing, The CA is processing your order, please just wait. (2/30)
[Fri Dec 15 10:14:24 2023] Success
[Fri Dec 15 10:14:24 2023] Removing DNS records.
[Fri Dec 15 10:14:25 2023] Removing txt: pORPIsBk1hTNFUHYwsm0YBT-4vM8BwBcYgkwIdvBdgQ for domain: _acme-challenge.qqq.ldlb.site
[Fri Dec 15 10:14:29 2023] Removed: Success
[Fri Dec 15 10:14:29 2023] Verify finished, start to sign.
[Fri Dec 15 10:14:30 2023] Lets finalize the order.
[Fri Dec 15 10:14:30 2023] Le_OrderFinalize='https://acme.cmc.test/acme/finalize/56/270'
[Fri Dec 15 10:14:33 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:14:37 2023] Polling order status: https://acme.cmc.test/acme/order/56/270
[Fri Dec 15 10:14:39 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:14:43 2023] Polling order status: https://acme.cmc.test/acme/order/56/270
[Fri Dec 15 10:14:45 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:14:49 2023] Polling order status: https://acme.cmc.test/acme/order/56/270
[Fri Dec 15 10:14:51 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:14:55 2023] Polling order status: https://acme.cmc.test/acme/order/56/270
[Fri Dec 15 10:14:57 2023] Downloading cert.
[Fri Dec 15 10:14:57 2023] Le_LinkCert='https://acme.cmc.test/acme/cert/74BFB4C9A7E6BE68CBEDD206B1274DB9FDDC3E93'
[Fri Dec 15 10:15:01 2023] Cert success.
...
[Fri Dec 15 10:15:01 2023] Your cert is in: /c/Users/xc/.acme.sh/qqq.ldlb.site/qqq.ldlb.site.cer
[Fri Dec 15 10:15:01 2023] Your cert key is in: /c/Users/xc/.acme.sh/qqq.ldlb.site/qqq.ldlb.site.key
[Fri Dec 15 10:15:01 2023] The intermediate CA cert is in: /c/Users/xc/.acme.sh/qqq.ldlb.site/ca.cer
[Fri Dec 15 10:15:01 2023] And the full chain certs is there: /c/Users/xc/.acme.sh/qqq.ldlb.site/fullchain.cer
成功签发了一张证书,最后四行说明了我们证书保存的位置:fullchain.cer
是证书链文件,qqq.ldlb.site.key
是证书私钥文件,qqq.ldlb.site.cer
是我们的证书,ca.cer
是中级CA证书
②查看证书
$ acme.sh --list
Main_Domain KeyLength SAN_Domains CA Created Renew
abcbcdwq.dasdsa.online "2048" no https://acme.cmc.test/acme/directory
bcbc.dasdsa.online "2048" no https://acme.cmc.test/acme/directory 2023-12-14T11:57:59Z 2024-02-11T11:57:59Z
qqq.ldlb.site "2048" no https://acme.cmc.test/acme/directory 2023-12-15T02:15:01Z 2024-02-12T02:15:01Z
第三张即是我们签发的证书
③安装证书
$ acme.sh --installcert -d qqq.ldlb.site --key-file d:/qqq.ldlb.site.key --fullchain-file d:/fullchain.cer --reloadcmd "echo Hello World"
[Fri Dec 15 10:28:16 2023] Installing key to: d:/qqq.ldlb.site.key
[Fri Dec 15 10:28:16 2023] Installing full chain to: d:/fullchain.cer
[Fri Dec 15 10:28:16 2023] Run reload cmd: echo Hello World
Hello World
[Fri Dec 15 10:28:16 2023] Reload success
查看我们指定的文件目录,相关证书已经被拷贝过去了,同时控制台也打印了Hello World
④手动续期
$ acme.sh --renew -d qqq.ldlb.site
[Fri Dec 15 10:31:50 2023] Renew: 'qqq.ldlb.site'
[Fri Dec 15 10:31:50 2023] Renew to Le_API=https://acme.cmc.test/acme/directory
[Fri Dec 15 10:31:51 2023] Skip, Next renewal time is: 2024-02-12T02:15:01Z
[Fri Dec 15 10:31:51 2023] Add '--force' to force to renew.
$ acme.sh --renew -d qqq.ldlb.site --force
[Fri Dec 15 10:32:10 2023] Renew: 'qqq.ldlb.site'
[Fri Dec 15 10:32:10 2023] Renew to Le_API=https://acme.cmc.test/acme/directory
[Fri Dec 15 10:32:15 2023] Using CA: https://acme.cmc.test/acme/directory
[Fri Dec 15 10:32:16 2023] Single domain='qqq.ldlb.site'
[Fri Dec 15 10:32:17 2023] Getting domain auth token for each domain
[Fri Dec 15 10:32:26 2023] Getting webroot for domain='qqq.ldlb.site'
[Fri Dec 15 10:32:28 2023] qqq.ldlb.site is already verified, skip dns-01.
[Fri Dec 15 10:32:29 2023] Verify finished, start to sign.
[Fri Dec 15 10:32:29 2023] Lets finalize the order.
[Fri Dec 15 10:32:29 2023] Le_OrderFinalize='https://acme.cmc.test/acme/finalize/56/271'
[Fri Dec 15 10:32:32 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:32:36 2023] Polling order status: https://acme.cmc.test/acme/order/56/271
[Fri Dec 15 10:32:38 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:32:42 2023] Polling order status: https://acme.cmc.test/acme/order/56/271
[Fri Dec 15 10:32:44 2023] Order status is processing, lets sleep and retry.
[Fri Dec 15 10:32:48 2023] Polling order status: https://acme.cmc.test/acme/order/56/271
[Fri Dec 15 10:32:51 2023] Downloading cert.
[Fri Dec 15 10:32:51 2023] Le_LinkCert='https://acme.cmc.test/acme/cert/B1EE89CB4E9A4115D4A97BEA2689946A761AD640'
[Fri Dec 15 10:32:54 2023] Cert success.
...
[Fri Dec 15 10:32:54 2023] Your cert is in: /c/Users/thomas.chen/.acme.sh/qqq.ldlb.site/qqq.ldlb.site.cer
[Fri Dec 15 10:32:54 2023] Your cert key is in: /c/Users/thomas.chen/.acme.sh/qqq.ldlb.site/qqq.ldlb.site.key
[Fri Dec 15 10:32:54 2023] The intermediate CA cert is in: /c/Users/thomas.chen/.acme.sh/qqq.ldlb.site/ca.cer
[Fri Dec 15 10:32:55 2023] And the full chain certs is there: /c/Users/thomas.chen/.acme.sh/qqq.ldlb.site/fullchain.cer
[Fri Dec 15 10:32:58 2023] Installing key to: d:/qqq.ldlb.site.key
[Fri Dec 15 10:32:58 2023] Installing full chain to: d:/fullchain.cer
[Fri Dec 15 10:32:58 2023] Run reload cmd: echo Hello World
Hello World
[Fri Dec 15 10:32:58 2023] Reload success
上面我们第一次执行手动执行acme.sh --renew -d qqq.ldlb.site
提示续期时间未到跳过,并提示我们加入--force
进行强制续期。
第二次执行命令acme.sh --renew -d qqq.ldlb.site --force
签发了一张新证书,控制台打印几乎与签发证书一致,只是结果多打印了一些内容,如下所示:
[Fri Dec 15 10:32:58 2023] Installing key to: d:/qqq.ldlb.site.key
[Fri Dec 15 10:32:58 2023] Installing full chain to: d:/fullchain.cer
[Fri Dec 15 10:32:58 2023] Run reload cmd: echo Hello World
Hello World
[Fri Dec 15 10:32:58 2023] Reload success
这正是我们安装证书的过程,可以预见acme.sh的定时任务在检测到有要到期的证书时促发续期,同时也会自动安装证书。
注意:测试过程使用–reloadcmd “echo Hello World”,实际上可能执行nginx -s reload
或docker restart
或kubectl rollout restart
等,你需要考虑定时任务促发执行该命令对业务的影响。