用 acme.sh 为多域名自动签发 Let's Encrypt 证书
背景
一台服务器上往往托管多个域名,手动续期证书是不可持续的。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。