背景

一台服务器上往往托管多个域名,手动续期证书是不可持续的。acme.sh 是一个纯 Shell 的 ACME 客户端,支持 http-01 与 dns-01 验证,能够被 cron 静默续期,是自建场景下的事实标准。

签发流程(http-01)

http-01 要求 CA 能访问 http://域名/.well-known/acme-challenge/<token>,因此 Nginx 必须把这个路径放行、且不能整体 301 到 HTTPS:

location ^~ /.well-known/acme-challenge/ {
    root /var/www/html;
    try_files $uri =404;
}

随后发起签发。ec-256 密钥在兼容性与性能之间最平衡:

acme.sh --issue -d dshost.me -d www.dshost.me -w /var/www/html --keylength ec-256

部署到 Nginx

签发得到的 fullchain 与私钥不要直接引用 ~/.acme.sh 内部目录,而是用 –install-cert 部署到固定路径,并注册 reload 钩子:

acme.sh --install-cert -d dshost.me \
  --key-file       /etc/nginx/ssl/dshost.me/dshost.me.key \
  --fullchain-file /etc/nginx/ssl/dshost.me/fullchain.cer \
  --reloadcmd      "nginx -s reload"

install-cert 会在每次续期后自动把新证书拷贝到目标路径并执行 reloadcmd,无需手工介入。

续期

acme.sh 默认安装一个每日 cron,仅在证书剩余有效期小于 30 天时续期。可用下面命令手动验证:

acme.sh --cron --force    # 强制续期一次(调试用)
acme.sh --list            # 查看已管理域名与到期时间

排坑

  • 挑战路径被 301:确认放行 location 使用 ^~ 前缀且未被 location / 的 return 覆盖。
  • 多域名共用一张证书:把 -d 并列即可,SAN 会包含所有域名。
  • 通配符必须 dns-01:*.example.com 无法用 http-01 验证,需配置 DNS API。