acme.sh 自动申请并续签 SSL 证书的工具
摘要
-
本文介绍自动申请并续签 SSL 证书的工具: acme.sh
acme.sh 介绍
-
acme.sh 实现了 acme 协议,可以从 ZeroSSL,Let’s Encrypt 等 CA 生成免费的证书。
-
适用场景:shell脚本方式,几乎无依赖,极简,适合不想安装Python环境的人。
-
特点:
- 纯 Shell 脚本,单文件运行
- 支持 100+ DNS API 自动续签(如 Cloudflare、阿里云、腾讯云等)
- 支持通配符证书
acme.sh 安装
-
需要先安装 crontab。以下以 RHEL/Fedora/CentOS 系为例;Debian/Ubuntu 可使用
apt install cron并启动cron服务,macOS 通常已内置 cron。
1 | # 安装 crontab(RHEL 系) |
-
安装 acme.sh
1 | # 安装成功后会自动安装到 ~/.acme.sh/ 目录下,证书也会生成在该目录下 |
升级 acme.sh
1 | # 升级 acme.sh 到最新版 |
卸载 acme.sh
1 | # --uninstall 会移除 cron 任务和 ~/.acme.sh 目录 |
生成证书
-
acme.sh 实现了 acme 协议支持的所有验证协议。
-
证书创建后会保存在 ~/.acme.sh/ 目录下,比如我的域名是
acme.hanqunfeng.com,则证书保存在~/.acme.sh/acme.hanqunfeng.com_ecc/目录下 -
创建证书时一般有两种方式验证: HTTP 和 DNS 验证。
HTTP 验证
-
支持多个子域名(通过多次
-d指定),但不支持通配符域名 -
需要提前将域名解析到本机的 IP 地址
直接签发
-
只需要指定域名,并指定域名所在的网站根目录。acme.sh 会全自动的生成验证文件,并放到网站的根目录,验证完成后会删除验证文件,整个过程没有任何副作用。
1 | # -d 指定域名,可以添加多个,--webroot 指定网站根目录 |
使用 Nginx/Apache 模式
-
如果你用的 Nginx/Apache 服务器,或者反代,acme.sh 还可以智能的从 Nginx/Apache 的配置中自动完成验证,你不需要指定网站根目录
-
nginx 或 httpd 命令要在系统 Path 中
1 | # -d 域名,可以添加多个, --nginx 告诉 acme.sh 使用 Nginx 模式 |
使用独立服务模式
-
如果服务器上没有运行任何 Web 服务,80 端口是空闲的,那么 acme.sh 还能临时监听 80 端口,完成验证
-
需要先安装 socat 命令,socat 常用于临时开启 TCP/UDP 监听端口
1 | sudo dnf install socat -y |
-
生成证书,要求 80 端口空闲,否则会失败
1 | # --standalone 独立服务模式 |
DNS 验证
-
如果你没有服务器,没有公网 IP,只需要 DNS 的解析记录即可完成验证。
-
支持通配符域名(通配符需加引号,防止 shell 展开
*)
手动验证
-
这需要你手动在域名上添加 TXT 解析记录,验证域名所有权。
-
注意:手动验证无法自动续签。每次续签(含首次
--renew)都需要按提示重新添加新的 TXT 记录。生产环境请优先使用 DNS API 自动验证。
1 | # 需要加上 --yes-I-know-dns-manual-mode-enough-go-ahead-please 选项 |
-
然后,acme.sh 会生成相应的解析记录显示出来,你只需要在你的域名管理面板中添加这条 TXT 记录即可。
1 | Add the following txt record: |
-
等待解析生效后,执行以下命令完成签发:
1 | # 续签/完成签发时需同样带上确认参数 |
自动验证(DNS API)
-
DNS 方式的真正强大之处在于可以使用域名解析商提供的 API 自动添加 TXT 记录,且在完成验证后删除对应的记录。
-
acme.sh 目前支持超过一百家的 DNS API。
-
以阿里云为例,登录阿里云帐号,获取 AccessKey 和 SecretKey,并设置环境变量:
1 | # 只需要命令行执行一次,运行生成证书命令时会保存在 ~/.acme.sh/account.conf 中,并在需要时自动获取,无需手动再设置 |
-
生成证书
1 | # --dns dns_ali 指定阿里云的 DNS API;通配符域名需加引号 |
生成证书的其它说明
-
acme.sh 脚本默认 CA 服务商是 ZeroSSL,acme.sh 支持的 CA 服务商及其使用方法,可以在命令行中通过
--server指定
1 | # 这里使用 Let's Encrypt 的 CA 服务商 |
-
也可以设置全局默认的 CA 服务商,这样就不需要每次都指定
--server
1 | acme.sh --set-default-ca --server letsencrypt |
小贴士
- 部分用户反馈默认 CA ZeroSSL 偶发不稳定,获取证书时可能长时间停留在:
Pending,The CA is processing your order,please just wait.。可尝试切换为 Let’s Encrypt(--server letsencrypt或--set-default-ca),通常重试 2-3 次即可成功。 - Let’s Encrypt 默认证书链使用 ISRG Root X1,Android 7.1.1 以下等较老系统可能无法信任。若有老设备兼容需求,可考虑 ZeroSSL(链到 USERTrust RSA,对老 Android 更友好)。注意:Android 5.1 及更早设备可能还需在服务端配置 ZeroSSL 交叉签名证书链;ZeroSSL 免费版另有 90 天内 3 张证书 的限制。
- 常见根证书表(仅供参考,实际兼容性以 SSL Labs 检测结果为准)
| 根证书(CN) | 较老 Android | 常见签发方 | 备注 |
|---|---|---|---|
| ISRG Root X1 | ❌ 不兼容 | Let’s Encrypt | Android ≥ 7.1.1 才默认信任 |
| DST Root CA X3 | ✅ 兼容(已过期) | Let’s Encrypt 老版本 | 2021 年过期,仅历史参考 |
| GlobalSign Root R1 | ✅ 兼容 | GlobalSign | |
| USERTrust RSA Certification Authority | ✅ 兼容 | ZeroSSL, Sectigo | 老设备友好 |
| Starfield Root CA - G2 | ❌ 不兼容 | GoDaddy 新版 | |
| Starfield Root CA - G1 | ✅ 兼容 | GoDaddy 老版 | |
| GTS Root R1/R3 | ❌ 较老系统不兼容 | Google Trust Services | |
| Amazon Root CA 1 | ❌ 较老系统不兼容 | Amazon Trust |
-
可用 SSL Labs 查看完整证书链和各设备兼容性
-
查看已经生成的证书(
Renew列为预计续签时间,详见「自动续签机制」)
1 | acme.sh --list |
-
如果生成证书时失败,可以通过添加
--debug参数查看详细错误信息
1 | acme.sh --issue -d acme.hanqunfeng.com -d '*.hanqunfeng.com' --dns dns_ali --server letsencrypt --debug |
-
自动续签的触发条件、前提和排查方式,见下文「自动续签机制」一节。
自动续签机制
acme.sh 的自动续签不是「每天自动换一张新证书」,而是 cron 每天检查一次,只有满足条件时才会真正执行续签。
前提条件
以下情况才会进入自动续签流程:
| 条件 | 说明 |
|---|---|
| cron 任务存在且正常运行 | 安装时自动添加,也可用 acme.sh --install-cronjob 补装;crontab -l 应能看到 --cron 条目 |
| 证书仍由 acme.sh 管理 | 未对该域名执行 acme.sh --remove |
| 验证方式支持无人值守 | HTTP 模式(webroot / nginx / apache / standalone)、DNS API 模式(如 dns_ali)均支持 |
| 续签时验证环境仍可用 | webroot 路径未变、80 端口可达(standalone)、DNS API 密钥仍有效等 |
以下情况不会自动续签:
| 情况 | 说明 |
|---|---|
| DNS 手动验证 | 每次续签都需手动添加新的 TXT 记录,cron 只会报错提醒 |
| cron 缺失或服务未运行 | 证书到期前不会有任何自动操作 |
已执行 --remove |
该域名已从 acme.sh 续签列表中移除 |
| 续签时验证失败 | 如 DNS API 密钥失效、webroot 目录不存在、80 端口被占用等 |
什么时候会真正续签
cron 每天执行 acme.sh --cron,对每个已管理的证书逐一判断。满足以下任一条件即触发续签:
-
到达下次续签时间:默认在证书剩余约 30 天时续签(90 天有效期的证书,大约在第 60 天触发)。该时间保存在域名配置文件的
Le_NextRenewTime中。 -
CA 的 ARI 建议窗口已开始:Let’s Encrypt、ZeroSSL 等 CA 支持 ARI(RFC 9773) 时,可能按 CA 公布的
suggestedWindow提前续签(无需额外配置,acme.sh 自动遵循)。 -
手动强制:执行
acme.sh --renew -d <域名> --force。
简言之:平时不动作,到了续签窗口(或 CA 要求提前)才续签。
查看下次续签时间
1 | # --list 的 Renew 列即预计续签时间 |
示例输出(--list):
1 | Main_Domain KeyLength SAN_Domains CA Created Renew |
续签成功后会发生什么
-
更新
~/.acme.sh/<域名>_ecc/下的证书文件(.cer、.key、fullchain.cer等)。 -
若之前配置过
acme.sh --install-cert,会自动将新证书复制到 Nginx/Apache 指定路径,并执行--reloadcmd重载服务。 -
重新计算并写入下一次续签时间
Le_NextRenewTime。
注意:
--install-cert中的reloadcmd非常重要。证书可以自动续签,但如果没有正确的重载命令,Web 服务可能仍在使用旧证书。
手动强制续签
未到续签时间也可手动触发:
1 | # --issue 仅用于首次签发;续签用 --renew。--force 跳过时间检查 |
续签失败时排查
1 | # 模拟 cron 执行,查看详细输出 |
常见原因:cron 未安装、DNS API 密钥过期、webroot 路径变更、standalone 模式下 80 端口被占用。
生成证书后自动部署和更新
-
上面无论是 http 还是 dns 模式,生成证书后,都会在
~/.acme.sh/acme.hanqunfeng.com_ecc/目录下生成以下文件:
1 | ├── acme.hanqunfeng.com.cer |
-
我们可以手动将证书拷贝到真正使用证书的目录下。如果使用 Nginx 或 Apache,可以让 acme.sh 自动将证书拷贝到指定目录,并在续签后重载服务。以下命令只需运行一次,后续由 cron 自动完成更新和部署。
-
Nginx
参数说明:-d 为签发时的域名;--key-file 对应 Nginx 配置的私钥路径;--fullchain-file 对应证书链路径;--reloadcmd 为证书更新后的重载命令(也可用 nginx -s reload)。
1 | acme.sh --install-cert \ |
-
文件对应关系
| acme.sh 文件 | 含义 | 你配置的目标文件 |
|---|---|---|
acme.hanqunfeng.com.key |
私钥 (Private Key) | /path/to/keyfile/in/nginx/key.pem |
fullchain.cer |
证书 + 中间证书链 (Fullchain) | /path/to/fullchain/nginx/cert.pem |
-
Apache
参数说明:--cert-file 为域名证书;--key-file 为私钥;--fullchain-file 为完整证书链;--reloadcmd 为重载命令。
1 | acme.sh --install-cert \ |
-
文件对应关系
| acme.sh 文件 | 含义 | 你配置的目标文件 |
|---|---|---|
acme.hanqunfeng.com.key |
私钥 (Private Key) | /path/to/keyfile/in/apache/key.pem |
acme.hanqunfeng.com.cer |
仅域名证书 (Certificate) | /path/to/certfile/in/apache/cert.pem |
fullchain.cer |
证书 + 中间证书链 (Fullchain) | /path/to/fullchain/certfile/apache/fullchain.pem |
移除证书并停止自动续签
1 | # 从 acme.sh 管理中移除该域名(含续签配置和 cron 中的自动续签) |
其它ssl自动续签工具
| 工具 | 推荐场景 | 官网地址 | 依赖 |
|---|---|---|---|
| Certbot | 传统服务器、Nginx/Apache | https://certbot.eff.org/ | Python |
| Lego | 静态二进制、K8s | https://github.com/go-acme/lego | 无依赖 |
| cert-manager | K8s 集群 | https://cert-manager.io/ | K8s CRD |
| Caddy | 简单站点自动HTTPS | https://caddyserver.com/ | 无需单独工具 |
| Traefik | 微服务网关 | https://traefik.io/ | Docker/K8s |