告别手动更新:用acme.sh彻底实现SSL免费证书自动化

现在各大云厂商的免费 SSL 证书有效期基本都缩短到了 3 个月。作为开发者,每隔几个月就去手动申请、下载、上传、重启 Nginx,实在是一件非常繁琐且不科学的事情。

本文将记录一个高阶、优雅的运维方案:使用 acme.sh 配合 DNS API,实现 Let’s Encrypt 泛域名证书(如 *.aliyun.com)的全自动申请,并通过 SSH Deploy 钩子,将证书跨服务器自动推送到另一台运行 Docker Nginx 的节点上,实现真正的零维护、零停机时间(Zero Downtime)热重载。

1. 架构与场景说明

我们拥有两台服务器:

  • 服务器 A(证书管理机): 负责安装 acme.sh,与 DNS 服务商通信验证域名,并集中管理所有证书。
  • 服务器 B(Web 业务机): 运行具体的 Web 业务,使用 Docker 容器化部署的 Nginx 作为反向代理。

目标: 服务器 A 每天自动检查证书状态,一旦即将过期,自动向 Let’s Encrypt 申请新证书 -> 申请成功后通过 SSH 推送到服务器 B 的指定挂载目录 -> 触发服务器 B 的 Nginx 容器热重载。


2. 安装与环境准备 (服务器 A)

首先在管理机(服务器 A)上安装 acme.sh

1
2
curl https://get.acme.sh | sh -s email=你的邮箱@example.com
source ~/.bashrc

注意:切换默认 CA
acme.sh 目前默认的证书颁发机构是 ZeroSSL。如果你想使用 Let’s Encrypt,需要执行以下命令完成切换:

1
acme.sh --set-default-ca --server letsencrypt

3. 申请泛域名证书

申请泛域名(通配符)证书推荐使用 DNS API 验证方式。在终端配置你域名服务商(以阿里云为例)的 API 凭证:

3.1 配置环境变量

在服务器 A 上设置环境变量,acme.sh 会自动读取它们来操作 DNS 解析记录:

1
2
export Ali_Key="你的AccessKey ID"
export Ali_Secret="你的AccessKey Secret"

3.2 执行申请命令

执行申请命令,这里同时包含主域名和泛域名:

1
acme.sh --issue --dns dns_ali -d aliyun.com -d *.aliyun.com

3.3 (可选)将证书安装到本地机器

如果你的目标 Nginx 和申请证书的 acme.sh 运行在同一台服务器上,可以直接执行以下命令安装证书:

1
2
3
4
acme.sh --install-cert -d aliyun.com \
--key-file /etc/letsencrypt/live/acme/aliyun.com.key \
--fullchain-file /etc/letsencrypt/live/acme/aliyun.com.cer \
--reloadcmd "nginx -s reload"

4. 自动化部署:SSH Deploy 钩子

这是实现“跨服务器自动推送”的关键步骤。

4.1 准备 SSH 密钥,配置免密登录

在服务器 A 上生成 SSH 密钥对,并将公钥添加到服务器 B 的 ~/.ssh/authorized_keys 中,允许无密码登录。

1
2
3
# 在服务器 A 上
ssh-keygen -t rsa -b 4096
ssh-copy-id root@[服务器B的IP]

4.2 配置 SSH Deploy

1
2
3
4
5
6
7
8
9
10
# 目标服务器登录凭证
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_SERVER="服务器B的IP地址"

# 推送到目标服务器的绝对路径
export DEPLOY_SSH_KEYFILE="/data/nginx/cert/aliyun.com.key"
export DEPLOY_SSH_FULLCHAIN="/data/nginx/cert/aliyun.com.cer"

# 推送完成后,在目标服务器执行的 Nginx 热重载命令 (Docker 零停机方案)
export DEPLOY_SSH_REMOTE_CMD="docker exec nginx.private.yyn nginx -s reload"

4.3 执行一键部署与绑定

1
acme.sh --deploy -d aliyun.com -d *.aliyun.com --deploy-hook ssh 

只要执行成功一次,acme.sh 就会将这些路径变量永久记录在配置文件中。以后每次证书自动续签,它都会默默走一遍这个推送和重启的流程。

5. 常见问题答疑 (FAQ)

Q1: 首次执行部署时,提示 cp: cannot stat... No such file or directory

这是正常的良性报错。acme.sh 为了安全,在覆盖新证书前会尝试备份旧证书。因为是第一次推送,目标服务器上还没有旧文件可供备份,所以会报 cp 找不到文件的错误。脚本会忽略该报错并继续把新证书写入,第二次及以后的推送就不会再有这个提示了。

Q2: 如何测试自动化流程?强制续签会作废原有的证书吗?

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

强制申请下来的新证书和旧证书是相互独立的。 Let’s Encrypt 不会主动吊销旧证书,它依然有效,只是你的 Nginx 已经加载了全新的证书而已。请注意不要频繁测试,以免触发 Let’s Encrypt 每周 5 次的重复签发频率限制。

参考资料


告别手动更新:用acme.sh彻底实现SSL免费证书自动化
https://gzthss.com/2026/03/07/告别手动更新-用acme-sh彻底实现SSL免费证书自动化/
Author
GZTHSS
Posted on
March 7, 2026
Licensed under