用 acme.sh 自动续签通配符证书并部署到 Nginx
腾讯云免费 SSL 证书每 90 天需要手动申请一次,管理多个子域名证书非常繁琐。本文介绍如何使用 acme.sh + 阿里云 DNS API,在腾讯云服务器上实现通配符证书的全自动申请和续签,一张证书覆盖所有子域名,一次配置永久生效。
适用场景:
-
域名在阿里云管理
-
服务器在腾讯云(CentOS)
-
Web 服务器为 Nginx
-
有多个子域名需要 HTTPS
原理
-
通配符证书:
*.example.com可覆盖所有子域名,无需每个域名单独申请 -
DNS-01 验证:通过阿里云 API 自动添加 TXT 记录完成域名所有权验证,无需开放 80 端口
-
acme.sh:开源 ACME 客户端,支持自动续签和 deploy hook
-
cron 自动化:安装时自动写入 cron,到期前 30 天自动续签并重新部署
准备工作
1. 阿里云 RAM 子账号 API 密钥
进入阿里云控制台 → 访问控制 RAM → 用户 → 创建用户,勾选"OpenAPI 调用访问",授予权限:
-
AliyunDNSFullAccess
记录生成的 AccessKey ID 和 AccessKey Secret。
建议使用子账号而非主账号,最小化权限范围。
2. 服务器安装 git
# CentOS 8 需要先换源(官方源已停止维护)
sed -i 's/mirrorlist.centos.org/mirrors.aliyun.com\/centos/g' /etc/yum.repos.d/*.repo
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com|g' /etc/yum.repos.d/*.repo
yum clean all && yum makecache
yum install -y git
安装 acme.sh
使用 Gitee 镜像(国内服务器推荐):
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m your@email.com
source ~/.bashrc
安装完成后会自动写入 cron 任务,每天定时检查证书是否需要续签。
申请通配符证书
export Ali_Key="你的AccessKey_ID"
export Ali_Secret="你的AccessKey_Secret"
/root/.acme.sh/acme.sh --issue --dns dns_ali \
-d example.com \
-d *.example.com \
--server zerossl \
--dnssleep 60
参数说明:
-
--dns dns_ali:使用阿里云 DNS API 自动验证 -
--server zerossl:使用 ZeroSSL 作为 CA(对国内网络更友好) -
--dnssleep 60:等待 60 秒让 DNS 记录生效后再验证
成功后证书保存在:/root/.acme.sh/example.com_ecc/
部署证书到 Nginx
将通配符证书复制到所有子域名对应的 Nginx 证书路径:
# 替换所有子域名的证书文件
for domain in example.com sub1.example.com sub2.example.com; do
cp /root/.acme.sh/example.com_ecc/fullchain.cer /etc/nginx/${domain}_bundle.crt
cp /root/.acme.sh/example.com_ecc/example.com.key /etc/nginx/${domain}.key
done
nginx -t && nginx -s reload
配置自动续签 Deploy Hook
每次 acme.sh 自动续签后,执行以下命令让 Nginx 加载新证书:
/root/.acme.sh/acme.sh --install-cert -d example.com \
--reloadcmd "for domain in example.com sub1.example.com sub2.example.com; do \
cp /root/.acme.sh/example.com_ecc/fullchain.cer /etc/nginx/\${domain}_bundle.crt; \
cp /root/.acme.sh/example.com_ecc/example.com.key /etc/nginx/\${domain}.key; \
done && nginx -s reload"
配置完成后,后续续签全程无需人工介入。
Nginx 配置示例
每个子域名的 server 块保持原有配置不变,只需确保证书路径正确:
server {
listen 443 ssl;
server_name sub1.example.com;
ssl_certificate /etc/nginx/sub1.example.com_bundle.crt;
ssl_certificate_key /etc/nginx/sub1.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
验证证书
# 查看证书有效期
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
# 确认 cron 已配置
crontab -l | grep acme
常见问题
服务器申请时报 DNSSEC 错误
.cn 域名可能存在 DNSSEC 残留配置,Let's Encrypt 的二次验证对此较严格。 解决方法:换用 ZeroSSL(--server zerossl),兼容性更好。
服务器网络无法连接 CA
部分 CA 节点在国内访问不稳定,加上 --dnssleep 60 参数延长 DNS 等待时间,或换用其他 CA:
# 测试服务器能否访问各 CA
curl -s --connect-timeout 10 https://acme.zerossl.com/v2/DV90 | grep newNonce
curl -s --connect-timeout 10 https://acme-v02.api.letsencrypt.org/directory | grep newNonce
续签失败排查
# 查看 acme.sh 日志
cat /root/.acme.sh/acme.sh.log
# 手动触发续签(调试)
/root/.acme.sh/acme.sh --renew -d example.com --server zerossl --dnssleep 60 --force --debug
# 确认阿里云 API 密钥未过期
# 登录阿里云 RAM 控制台检查 AccessKey 状态
总结
| 步骤 | 操作 |
|---|---|
| 一次性配置 | 安装 acme.sh、申请证书、配置 deploy hook |
| 日常维护 | 无需操作,cron 自动续签 |
| 出问题时 | 查日志、手动 renew、检查 API 密钥 |
浙公网安备 33010602011771号