首页 acme.sh Cookbook
340px

入口与定位 >>>

纯 Shell 编写的 ACME 客户端,用于自动化获取、续期、安装 SSL/TLS 证书。无需 Python,兼容 Bash/dash/sh,支持 ECDSA 证书和通配符。
  • 解决的问题:自动化管理 Let's Encrypt、ZeroSSL 等 CA 的证书生命周期
  • 核心优势:
    • 纯 Shell,无依赖
    • 支持 80+ DNS Provider API 自动验证
    • 默认 ECC 证书,可选 RSA
    • 自动续期(默认 60 天)
    • 不需要 root 权限

安装与初始化

安装只有 3 步:下载、安装、验证。安装后会自动创建 cron job 用于续期。
# 方式一:一键安装(推荐)
curl https://get.acme.sh | sh -s email=your@email.com

# 方式二:Wget 安装
wget -O - https://get.acme.sh | sh -s email=your@email.com

# 方式三:手动安装
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m your@email.com
  • ~/.acme.sh/:存放所有证书和配置
  • acme.sh=~/.acme.sh/acme.sh
  • 自动创建每日 cron job 检查续期
# 手动更新到最新版本
acme.sh --upgrade

# 开启自动升级
acme.sh --upgrade --auto-upgrade

验证方式选择

根据你的环境选择合适的验证方式。DNS 模式最通用,Webroot 适合有现成网站的场景。
模式适用场景需要端口
Webroot有现成网站目录
Standalone无网站,仅有服务器80 (TCP)
TLS-ALPN无网站,仅有服务器443 (TCP)
DNS任何场景,特别是通配符
Apache / Nginx正在运行对应 Web 服务器

Webroot 模式

适用于已有 Web 服务器的场景。acme.sh 会把验证文件写到网站根目录,CA 通过 HTTP 访问验证。
# 单域名
acme.sh --issue -d example.com -w /home/wwwroot/example.com

# 多域名(同一证书)
acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com

# 通配符(需要 DNS API)
acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf

Standalone 模式

无需 Web 服务器,acme.sh 内置临时 Web Server 监听 80 端口完成验证。
# HTTP 验证(需要 80 端口)
acme.sh --issue --standalone -d example.com -d www.example.com

# TLS-ALPN 验证(需要 443 端口)
acme.sh --issue --alpn -d example.com -d www.example.com

DNS 模式(最通用)

通过 DNS TXT 记录验证,支持 80+ DNS Provider。最适合通配符证书和无法开放端口的场景。

Cloudflare 示例

# 设置 API Token(推荐)
export CF_Token="your_cloudflare_token"
export CF_Account_ID="your_account_id"

# 颁发证书
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

常用 DNS Provider

# Cloudflare
export CF_Token="xxx"
--dns dns_cf

# DNSPod
export DP_Id="id"
export DP_Key="key"
--dns dns_dp

# AWS Route53
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"
--dns dns_aws

# Aliyun
export Ali_Key="xxx"
export Ali_Secret="xxx"
--dns dns_ali

# DigitalOcean
export DO_API_KEY="xxx"
--dns dns_dgon

DNS 手动模式(无法自动时)

# 手动添加 TXT 记录
acme.sh --issue --dns -d example.com

# 按提示添加 DNS 记录后,手动续期
acme.sh --renew -d example.com

# ⚠️ 警告:手动模式无法自动续期!

证书安装到服务器

证书生成后,必须用 --install-cert 复制到目标路径。不要直接使用 ~/.acme.sh/ 下的文件!
# 安装到 Nginx
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.fullchain.pem \
  --reloadcmd "systemctl reload nginx"

# 安装到 Apache
acme.sh --install-cert -d example.com \
  --cert-file /etc/apache2/ssl/example.com.crt \
  --key-file /etc/apache2/ssl/example.com.key \
  --fullchain-file /etc/apache2/ssl/example.com.fullchain.pem \
  --reloadcmd "systemctl reload apache2"
  • --reloadcmd:续期后自动重载服务,否则用户看不到新证书!

证书续期

acme.sh 默认 60 天自动续期。也可以手动强制续期。
# 手动续期指定域名
acme.sh --renew -d example.com

# 强制续期(忽略证书有效期)
acme.sh --renew -d example.com --force

# 手动触发所有证书检查
acme.sh --cron

# 列出所有证书
acme.sh --list

# 移除证书(停止续期)
acme.sh --remove -d example.com

证书类型选择

默认 ECDSA(更小、更安全)。根据需求选择密钥长度。
参数类型推荐场景
ec-256ECDSA P-256默认,移动端兼容性好
ec-384ECDSA P-384高安全要求
ec-521ECDSA P-521最高安全要求
4096RSA 4096-bit兼容老旧系统
# ECDSA 证书(默认)
acme.sh --issue -d example.com --keylength ec-256

# RSA 证书
acme.sh --issue -d example.com --keylength 4096

切换 CA

acme.sh 默认使用 ZeroSSL,可切换到 Let's Encrypt、Google Public CA 等。
# 切换到 Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

# 切换到 ZeroSSL(默认)
acme.sh --set-default-ca --server zerossl

# 使用 Google Public CA
acme.sh --set-default-ca --server google

# 查看支持的 CA 列表
acme.sh --server list

常见场景 Recipes

直接复制这些模板到你的项目中使用。

场景一:Nginx 站点 + 单域名

# 1. 获取证书
acme.sh --issue -d example.com -w /var/www/html

# 2. 安装证书
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.pem \
  --reloadcmd "nginx -s reload"

场景二:Nginx 站点 + 通配符

# 1. 配置 Cloudflare
export CF_Token="xxx"

# 2. 获取通配符证书
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

# 3. 安装
acme.sh --install-cert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.pem \
  --reloadcmd "nginx -s reload"

场景三:Docker 中使用

# 在 Docker 中运行
docker run --rm -it \
  -v "$(pwd)/acme.sh":/acme.sh \
  -e CF_Token="xxx" \
  neilpang/acme.sh \
  --issue --dns dns_cf -d example.com -d '*.example.com'

# 复制证书到宿主机
docker run --rm -it \
  -v "$(pwd)/acme.sh":/acme.sh \
  -v "$(pwd)/certs":/certs \
  neilpang/acme.sh \
  --install-cert -d example.com \
  --cert-file /certs/cert.pem \
  --key-file /certs/key.pem

场景四:多域名证书

# 3 个域名同一证书
acme.sh --issue \
  -d example.com \
  -d www.example.com \
  -d mail.example.com \
  -w /home/wwwroot/example.com

常见坑

这些问题新手容易遇到,提前避开省时间。

1. 端口被占用

# Standalone 报 "Port 80 is already used"
# 方案:先停掉占用 80 端口的服务,或改用 Webroot 模式
lsof -i :80

2. 续期后服务没重载

# 原因:--reloadcmd 写错了
# 检查:手动执行 reloadcmd 确认路径正确
systemctl reload nginx

3. DNS API 权限不足

# Cloudflare: Token 需要 Zone > DNS > Edit 权限
# AWS: 需要 Route53 权限
# 检查日志:tail -f /var/log/acme.sh/log

4. 证书路径找不到

# 不要直接用 ~/.acme.sh/example.com/ 下的文件!
# 必须用 --install-cert 复制到目标位置
# 原因:内部文件结构可能变化

5. 泛域名 + 多域名混合

# 正确:一起申请
acme.sh --issue --dns dns_cf \
  -d example.com \
  -d '*.example.com' \
  -d www.example.com

# ❌ 错误:分开申请会导致验证顺序问题

Docker 部署 Checklist

在 CI/CD 中使用 acme.sh 时,按这个清单检查。
# ✅ 检查清单
# 1. DNS API Token 已设置
# 2. 证书目录已挂载(-v)
# 3. reloadcmd 在宿主机执行(不在容器内)
# 4. 确认 60 天内至少运行过一次 --cron

# 推荐:使用 DNS 自动验证,兼容任何服务器

进阶:使用已有 CSR

如果已有私钥或 CSR,可以复用。
# 使用已有 CSR
acme.sh --issue --csr /path/to/example.com.csr -d example.com

# 指定已有私钥
acme.sh --issue -d example.com --key-file /path/to/key.pem

通知配置

配置证书续期或错误的通知渠道。
# 邮件通知
acme.sh --notify --notifymail mail@example.com

# Webhook 通知
# 参考:https://github.com/acmesh-official/acme.sh/wiki/notify