51 说明
neil edited this page 2026-05-01 15:12:07 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

acme.sh 实现了 acme 协议,可以从 ZeroSSLLet's Encrypt 等 CA 生成免费的证书。

主要步骤:

  1. 安装 acme.sh

  2. 生成证书

  3. 安装证书到 Nginx/Apache 或者其他服务

  4. 更新证书

  5. 更新 acme.sh

  6. 出错怎么办,如何调试

下面详细介绍.

1. 安装 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

普通用户和 root 用户都可以安装使用。

安装过程进行了以下几步:

  1. 把 acme.sh 安装到你的 home 目录下:
~/.acme.sh/

并创建 一个 shell 的 alias例如 .bashrc,方便你的使用: alias acme.sh=~/.acme.sh/acme.sh

  1. 自动为你创建 cronjob 每天 0:00 点自动检测所有的证书,如果达到自动更新的天数阈值,则会自动更新证书。

更高级的安装选项请参考: https://github.com/acmesh-official/acme.sh/wiki/How-to-install

安装过程不会污染已有的系统任何功能和文件,所有的修改都限制在安装目录中: ~/.acme.sh/

注意:如果安装完成后提示 -bash: acme.sh: command not found,需要手动执行 source ~/.bashrc

2. 生成证书

acme.sh 实现了 acme 协议支持的所有验证协议。

一般有两种方式验证: HTTP 和 DNS 验证。

HTTP 验证

直接签发

只需要指定域名,并指定域名所在的网站根目录. acme.sh 会全自动的生成验证文件,并放到网站的根目录,验证完成后会聪明地删除验证文件,整个过程没有任何副作用。

acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

支持letsencrypt的ip证书 及certificate profile

acme.sh --issue -d 203.0.113.195 -w /home/username/public_html --server letsencrypt_test --certificate-profile shortlived --days 6

使用 Apache 模式

如果你用的 Apache 服务器,acme.sh 还可以智能地从 Apache 的配置中自动完成验证,你不需要指定网站根目录:

acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com

使用 Nginx 模式

如果你用的 Nginx 服务器,或者反代,acme.sh 还可以智能地从 Nginx 的配置中自动完成验证,你不需要指定网站根目录:

acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com

注意,无论是 Apache 还是 Nginx 模式acme.sh 在完成验证之后,会恢复到之前的状态,都不会私自更改程序本身的配置。好处是你不用担心配置被搞坏,也有一个缺点,你需要自己配置 SSL 项,否则只能成功生成证书,你的网站还是无法正常使用 HTTPS。

使用独立服务模式

如果服务器上没有运行任何 Web 服务,80 端口是空闲的,那么 acme.sh 还能假装自己是一个 WebServer临时监听 80 端口,完成验证:

acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com

修改默认 CA

acme.sh 脚本默认 CA 服务器是 ZeroSSL,有时可能会导致获取证书的时候一直出现:PendingThe CA is processing your orderplease just wait.

只需要把 CA 服务器改成 Let's Encrypt 即可,虽然更改以后还是有概率出现 pending但基本 2-3 次即可成功

acme.sh --set-default-ca --server letsencrypt

更高级的用法请参考: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert

DNS 验证

如果你没有服务器,没有公网 IP只需要 DNS 的解析记录即可完成验证。

手动验证

这需要你手动在域名上添加一条 TXT 解析记录,验证域名所有权。

注意如果使用手动验证acme.sh 将无法自动更新证书,每次都需要手动添加解析来验证域名所有权。如果有自动更新证书的需求,但 DNS 服务商没有 API推荐使用下面的「DNS Persist 模式」。

acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com

然后,acme.sh 会生成相应的解析记录显示出来,你只需要在你的域名管理面板中添加这条 TXT 记录即可。

等待解析完成之后,执行以下命令重新生成证书:

acme.sh --renew -d mydomain.com

注意这里现在用的是 --renew 参数

DNS Persist 模式(持久化 DNS 验证,无 API 也能自动续签)

如果你的 DNS 服务商没有 API但你能编辑一次解析记录DNS Persist 模式让你只添加一条长期有效的 TXT 记录,之后续签全程自动,不再需要每次改 DNS

实现的是 IETF 草案 draft-ietf-acme-dns-persist-01

# 第 1 步:打印需要添加的 TXT 记录值
acme.sh --make-dns-persist-value -d example.com

# 第 2 步:在你的 DNS 服务商面板里添加打印出来的 _validation-persist.example.com TXT 记录,等待解析生效

# 第 3 步:签发
acme.sh --issue -d example.com --dns-persist

可选参数(用在第 1 步):

参数 作用
--server <ca> 指定 CA(默认是你已配置的默认 CA)。如果还没在该 CA 注册过账户,会自动注册。
--dns-persist-wildcard 给记录加 policy=wildcard,同时授权通配符 / 子域证书。
--dns-persist-ca-name <name> 指定特定的 CA 标识域名(例如 ssl.com)。省略时,从 ACME directory 的 caaIdentities 字段读取,每个标识各打印一条记录(任选其一添加即可)。
--dns-persist-days <N> 给记录加 persistUntil 字段,使记录在 N 天后自动失效(CA 之后不再接受针对该记录的新验证)。省略则永不过期。

之后 cron 会自动续签,这条 TXT 记录会被反复复用,无需再动 DNS。

详见: https://github.com/acmesh-official/acme.sh/wiki/DNS-persist-mode

自动验证DNS API

DNS 方式的真正强大之处在于可以使用域名解析商提供的 API 自动添加 TXT 记录,且在完成验证后删除对应的记录。

acme.sh 目前支持超过一百家的 DNS API。

以 DNSPod.cn 为例,你需要先登录到 DNSPod.cn,拿到你的 DNSPod API Key 和 ID 并设置:

export DP_Id="1234"

export DP_Key="sADDsdasdgdsf"

现在我们可以签发通配符证书了:

acme.sh --issue --dns dns_dp -d example.com -d *.example.com

DP_IdDP_Key 将保存在 ~/.acme.sh/account.conf 中,并在需要时自动获取,无需手动再设置。

更详细的 DNS API 用法: https://github.com/acmesh-official/acme.sh/wiki/dnsapi

3. 复制证书

证书生成好以后,我们需要把证书复制给对应的 Apache、Nginx 或其他服务器去使用。

必须使用 --install-cert 命令来把证书复制到目标文件,请勿直接使用 ~/.acme.sh/ 目录下的证书文件,这里面的文件都是内部使用,而且目录结构将来可能会变化。

Apache 示例:

acme.sh --install-cert -d example.com \
--cert-file      /path/to/certfile/in/apache/cert.pem  \
--key-file       /path/to/keyfile/in/apache/key.pem  \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd     "service apache2 force-reload"

Nginx 示例:

acme.sh --install-cert -d example.com \
--key-file       /path/to/keyfile/in/nginx/key.pem  \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd     "service nginx force-reload"

Nginx 的配置项 ssl_certificate 需要使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/<domain>.cer ,否则 SSL Labs 的测试会报证书链问题(Chain issues Incomplete)。

默认情况下,证书每 60 天更新一次可自定义。更新证书后Apache 或者 Nginx 服务会通过 reloadcmd 传递的命令自动重载配置。

注意:reloadcmd 非常重要。证书会自动申请续签,但是如果没有正确的 reloadcmd 命令,证书可能无法被重新应用到 Apache 或者 Nginx因为配置没有被重载。

4. 查看已安装证书信息

acme.sh --info -d example.com

会输出如下内容:

DOMAIN_CONF=/root/.acme.sh/example.com/example.com.conf
Le_Domain=example.com
Le_Alt=no
Le_Webroot=dns_ali
Le_PreHook=
Le_PostHook=
Le_RenewHook=
Le_API=https://acme-v02.api.letsencrypt.org/directory
Le_Keylength=
Le_OrderFinalize=https://acme-v02.api.letsencrypt.org/acme/finalize/23xxxx150/781xxxx4310
Le_LinkOrder=https://acme-v02.api.letsencrypt.org/acme/order/233xxx150/781xxxx4310
Le_LinkCert=https://acme-v02.api.letsencrypt.org/acme/cert/04cbd28xxxxxx349ecaea8d07
Le_CertCreateTime=1649358725
Le_CertCreateTimeStr=Thu Apr  7 19:12:05 UTC 2022
Le_NextRenewTimeStr=Mon Jun  6 19:12:05 UTC 2022
Le_NextRenewTime=1654456325
Le_RealCertPath=
Le_RealCACertPath=
Le_RealKeyPath=/etc/acme/example.com/privkey.pem
Le_ReloadCmd=service nginx force-reload
Le_RealFullChainPath=/etc/acme/example.com/chain.pem

5. 更新证书

证书自动更新,你无需任何操作。默认每 30 天自动更新一次,或者更早——如果 CA 通过 ACME Renewal Information(ARI,RFC 9773)告知应当提前续签时,acme.sh 会自动遵守。

ARI 完全自动,没有任何参数,无需开启。如果 CA 的 directory 里没有 renewalInfo 端点,自动退回经典的 30 天规则,行为不变。

详见: https://github.com/acmesh-official/acme.sh/wiki/ARI

如果想立即强制续签,可以:

acme.sh --renew -d example.com --force

查看下次续签时间:

acme.sh --info -d example.com
# 看 Le_NextRenewTimeStr 字段

6. 关于修改 reloadcmd

目前修改 reloadcmd 没有专门的命令,可以通过重新安装证书来实现修改 reloadcmd 的目的。

此外,安装证书后,相关信息是保存在 ~/.acme.sh/example.com/example.conf 文件下的,内容就是 acme.sh --info -d example.com 输出的信息,不过 reloadcmd 在文件中使用了 Base64 编码。理论上可以通过直接修改该文件来修改 ReloadCmd,且修改时,无需 Base64 编码,直接写命令原文 acme.sh 也可以识别。

不过,由于 example.conf 文件的位置和内容格式以后可能会改变,且 example.conf 一直都是内部使用,后续也有可能会改为用 SQLite 或者 MySQL 格式存储。所以一般不建议自己修改。

7. 更新 acme.sh

acme.sh 还在不断开发中,因此强烈建议保持并使用最新的版本。

升级 acme.sh 到最新版:

acme.sh --upgrade

如果你不想手动升级,可以开启自动升级:

acme.sh --upgrade --auto-upgrade

之后acme.sh 就会自动保持更新了。

你也可以随时关闭自动更新:

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

8. 出错怎么办:

如果出错,请添加 --debug 参数输出详细的调试信息:

acme.sh --issue  .....  --debug 

或者输出更详细的信息:

acme.sh --issue  .....  --debug  2

请参考:https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh

在 DNS 验证模式下如果 debug 中出现诸如 timed out 等字样可能是因为 GFW HTTP(S) Proxy 环境变量。(请按照自己实际设定修改)

export http_proxy="socks5h://localhost:1081"
export https_proxy="socks5h://localhost:1081" 

如果是使用 docker 则完整示例配置如下:

docker run --rm  -it  \
  -v "/etc/acme":/acme.sh  \
  -e "CF_Token=[填入自己的信息]" \
  -e "CF_Account_ID=[填入自己的信息]" \
  -e "CF_Zone_ID=[填入自己的信息]" \
  -e http_proxy="socks5h://[代理A]:1234" \
  -e https_proxy="socks5h://[代理A]:1234" \
  --network container:[代理A]\
  neilpang/acme.sh \
  --issue -d example.com --dns dns_cf --debug

上述例子中使用 Cloudflare 的 DNS 来签发证书,并通过把 acme.sh 链接到容器[代理A],来转发 curl 请求(请按照自己实际设定修改)


最后,本文并非完全的使用说明,还有很多高级的功能,更高级的用法请参看 wiki 页面:https://github.com/acmesh-official/acme.sh/wiki/