为什么选择 acme.sh

在证书自动化管理领域,Certbot 是最知名的 ACME 客户端,但它依赖 Python 环境,体积较大。acme.sh 是一个纯 Shell 编写的轻量级 ACME 客户端,优势明显:

  • 零依赖:仅需 curlsed,可在任意 Linux 发行版运行
  • 体积小巧:安装包仅几百 KB
  • 支持 DNS API:可自动申请通配符证书
  • 兼容性强:支持 Let’s Encrypt、ZeroSSL、Buypass 等多 CA

安装 acme.sh

方式一:在线安装(推荐)

1
curl https://get.acme.sh | sh -s email=admin@example.com

安装完成后,acme.sh 会自动创建配置目录 ~/.acme.sh/,并添加 cron 任务实现自动续期。

方式二:离线安装

在没有网络的环境下,可以先在其他机器下载安装脚本:

1
2
3
4
5
6
# 在有网络的机器上下载
curl https://get.acme.sh > install.sh

# 传输到目标机器后安装
chmod +x install.sh
./install.sh --online no -s email=admin@example.com

验证安装

1
acme.sh --version

输出类似:

1
acme.sh version 3.0.9

申请证书:HTTP 验证方式

HTTP 验证是最简单的证书申请方式,需要 80 端口开放。

1. 申请单域名证书

1
acme.sh --issue -d example.com -w /var/www/html

-d 指定域名,-w 指定网站根目录。acme.sh 会在该目录下创建 .well-known/acme-challenge/ 目录用于验证。

2. 申请多域名证书

1
acme.sh --issue -d example.com -d www.example.com -w /var/www/html

3. 使用 Nginx 自动模式

acme.sh 可以自动配置 Nginx,无需手动放置验证文件:

1
acme.sh --issue -d example.com --nginx

此命令会自动修改 Nginx 配置,完成验证后再恢复。

申请证书:DNS 验证方式

DNS 验证不需要开放端口,支持申请通配符证书。

1. 配置 DNS API

acme.sh 支持数十种 DNS 提供商的 API 自动验证。以 Cloudflare 为例:

1
2
export CF_Key="your_cloudflare_api_key"
export CF_Email="your_email@example.com"

⚠️ 安全提示:API 密钥建议写入 acme.sh 配置文件,而非命令行历史记录。

2. 申请通配符证书

1
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

3. 其他常用 DNS 提供商

提供商 环境变量 命令参数
Cloudflare CF_Key, CF_Email dns_cf
阿里云 Ali_Key, Ali_Secret dns_ali
腾讯云 TXY_SECRET_ID, TXY_SECRET_KEY dns_tx
DNSPod DP_Id, DP_Key dns_dp
GoDaddy GD_Key, GD_Secret dns_gd

完整列表参考:acme.sh DNS API 支持列表

证书安装与部署

申请到证书后,需要将证书安装到实际使用的位置。

1. 安装证书到指定目录

1
2
3
4
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com/key.pem \
  --fullchain-file /etc/nginx/ssl/example.com/cert.pem \
  --reloadcmd "nginx -s reload"

参数说明:

  • --key-file:私钥保存路径
  • --fullchain-file:完整证书链保存路径
  • --reloadcmd:证书更新后自动重载服务的命令

2. 使用 standalone 模式

如果不想修改现有配置,可以使用 standalone 模式:

1
2
3
acme.sh --install-cert -d example.com \
  --key-file ./key.pem \
  --fullchain-file ./cert.pem

然后在 Nginx 配置中引用:

1
2
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

自动续期配置

acme.sh 安装时会自动添加 cron 任务:

1
2
# 查看 cron 任务
crontab -l

输出类似:

1
0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

默认每天凌晨检查证书是否需要续期。续期逻辑:

  1. 证书距离过期少于 30 天时自动续期
  2. 续期成功后执行 --install-cert 时指定的 --reloadcmd
  3. 失败时记录日志,不影响服务运行

手动触发续期

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

强制续期

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

证书管理常用命令

查看已安装证书

1
acme.sh --list

输出格式:

1
2
Main_Domain          KeyLength  CreatedDate              RenewDate
example.com          2048       2026-07-09T00:08:46Z     2026-08-08T00:08:46Z

撤销证书

1
acme.sh --revoke -d example.com

删除证书

1
acme.sh --remove -d example.com

导出证书为其他格式

1
2
3
4
5
# 导出为 PFX 格式(适用于 IIS)
acme.sh --export -d example.com -f pfx --pfxpass yourpassword

# 导出为 PKCS12
acme.sh --export -d example.com -f pkcs12 --password yourpassword

实际案例:Nginx HTTPS 配置

完整演示从申请证书到配置 Nginx 的流程。

步骤 1:安装 acme.sh

1
curl https://get.acme.sh | sh -s email=admin@example.com

步骤 2:申请证书(DNS 方式)

1
2
3
export CF_Key="your_cloudflare_api_key"
export CF_Email="your_email@example.com"
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

步骤 3:创建证书目录并安装

1
2
3
4
5
mkdir -p /etc/nginx/ssl/example.com
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com/key.pem \
  --fullchain-file /etc/nginx/ssl/example.com/cert.pem \
  --reloadcmd "nginx -s reload"

步骤 4:配置 Nginx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/key.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    location / {
        root /var/www/html;
        index index.html;
    }
}

步骤 5:强制续期测试

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

确认证书更新后 Nginx 自动重载:

1
nginx -t && nginx -s reload

常见问题

Q: 证书申请失败,提示 “Validate error”

检查以下内容:

  1. 域名是否正确解析到当前服务器 IP
  2. 80 端口(Nginx 验证)或 443 端口是否开放
  3. 防火墙是否放行了相应端口
  4. 网站根目录权限是否正确

Q: DNS 验证失败

  1. 确认 API 密钥正确
  2. DNS 记录传播可能需要几分钟,等待后重试
  3. 使用 --debug 2 查看详细日志

Q: 续期后服务未重载

  1. 检查 --reloadcmd 命令是否正确
  2. 查看日志:cat ~/.acme.sh/acme.sh.log
  3. 确认 cron 任务是否存在

Q: 切换 CA 提供商

1
2
3
4
5
# 切换到 ZeroSSL
acme.sh --set-default-ca --server zerossl

# 切换回 Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

参考来源