使用 acme.sh + Let’s Encrypt + 阿里云 DNS API 实现泛域名 SSL 自动续签与自动部署

MTL_Sakura 发布于 8 小时前 8 次阅读


1. 背景

我之前使用的是阿里云提供的免费 SSL 证书,但这类免费证书通常有效期较短,需要定期手动更新。手动更新的问题在于:

  • 每隔一段时间就要重新申请证书;
  • 需要手动下载证书;
  • 需要手动上传到服务器或宝塔面板;
  • 忘记更新会导致 HTTPS 证书过期;
  • 多个子域名分别管理证书会非常麻烦。

因此,我最终选择了:

acme.sh + Let’s Encrypt + 阿里云 DNS API

目标是实现:

免费 SSL 证书
+ 泛域名证书
+ 自动 DNS 验证
+ 自动续签
+ 自动部署到 Nginx
+ 自动部署到宝塔面板

最终效果是:

snowmoon1824.top
*.snowmoon1824.top

都可以使用同一张泛域名证书。


2. 整体方案说明

本方案的核心逻辑是:

acme.sh 负责申请和续签证书
Let’s Encrypt 负责签发免费 SSL 证书
阿里云 DNS API 负责自动完成 DNS 验证
Nginx 使用统一证书路径
宝塔面板 SSL 目录同步使用同一张证书

整体链路如下:

acme.sh 定时任务
→ 到期前自动向 Let’s Encrypt 续签证书
→ 通过阿里云 DNS API 自动添加 TXT 验证记录
→ DNS 验证成功后签发新证书
→ 自动更新 /etc/nginx/ssl/snowmoon1824.top/
→ 自动执行部署脚本
→ reload Nginx
→ 同步证书到宝塔面板 SSL 目录
→ restart 宝塔面板

3. 为什么选择 DNS-01 验证?

Let’s Encrypt 申请证书时,需要验证域名所有权。常见验证方式有两种:

验证方式说明是否适合泛域名
HTTP-01在网站目录放置验证文件不适合泛域名
DNS-01添加 _acme-challenge TXT 解析记录适合泛域名

因为我要申请的是:

*.snowmoon1824.top

所以必须使用 DNS-01 验证。

DNS-01 验证的流程是:

Let’s Encrypt 要求添加 TXT 记录
→ acme.sh 调用阿里云 DNS API
→ 自动添加 _acme-challenge.snowmoon1824.top TXT 记录
→ Let’s Encrypt 验证通过
→ acme.sh 自动删除临时 TXT 记录
→ 证书签发成功

这样不需要手动去阿里云控制台添加 TXT 记录。


4. 准备工作

4.1 域名

本次使用的域名是:

snowmoon1824.top

目标证书覆盖:

snowmoon1824.top
*.snowmoon1824.top

其中:

*.snowmoon1824.top

可以覆盖所有一级子域名,例如:

blog.snowmoon1824.top
bt.snowmoon1824.top
api.snowmoon1824.top
nav.snowmoon1824.top
www.snowmoon1824.top

但不能覆盖二级子域名,例如:

a.b.snowmoon1824.top
test.api.snowmoon1824.top

原因是通配符证书 *.snowmoon1824.top 只匹配一级子域名。


4.2 服务器环境

本次环境为:

阿里云 ECS
宝塔面板
Nginx
root 用户 SSH 操作

宝塔 Nginx 站点配置目录为:

/www/server/panel/vhost/nginx/

宝塔面板 SSL 目录为:

/www/server/panel/ssl/

普通网站统一 SSL 证书目录设定为:

/etc/nginx/ssl/snowmoon1824.top/

4.3 阿里云 RAM 用户

不要直接使用阿里云主账号 AccessKey。
应该创建一个专门用于 acme.sh 的 RAM 子用户。

推荐用户名称:

acme-dns

创建用户时:

配置项选择
控制台访问不开启
AccessKey 访问开启
MFA不需要
安全手机 / 安全邮箱可以不填

创建完成后,需要保存:

AccessKey ID
AccessKey Secret

注意:

AccessKey Secret 只在创建时显示一次,之后不能再次查看。

如果忘记保存,只能重新创建 AccessKey。


4.4 RAM 用户授权

给这个 RAM 用户添加权限:

AliyunDNSFullAccess

原因是 acme.sh 需要通过阿里云 DNS API 自动添加和删除 TXT 记录。

如果没有 DNS 权限,申请证书时会报错,例如:

Error adding TXT record to domain

或者:

You don't specify aliyun api key and secret yet.

5. 安装 acme.sh

SSH 登录服务器后,执行:

curl https://get.acme.sh | sh -s email=你的邮箱

例如:

curl https://get.acme.sh | sh -s email=xduzhangyujian@outlook.com

安装完成后执行:

source ~/.bashrc

检查是否安装成功:

~/.acme.sh/acme.sh --version

如果能看到版本号,说明安装成功。


6. 设置默认 CA 为 Let’s Encrypt

acme.sh 可能默认使用其他 CA,例如 ZeroSSL。为了明确使用 Let’s Encrypt,执行:

~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

这么做的原因是:

避免 acme.sh 默认使用其他 CA
保证本次证书由 Let’s Encrypt 签发

7. 配置阿里云 DNS API 密钥

在当前 SSH 终端中执行:

export Ali_Key="你的AccessKey_ID"
export Ali_Secret="你的AccessKey_Secret"

注意:

  • Ali_KeyAli_Secret 大小写必须完全正确;
  • = 左右不能有空格;
  • 不要把尖括号复制进去;
  • 不要把 Secret 发给别人;
  • 不要把 AccessKey 上传到 GitHub。

正确格式示例:

export Ali_Key="LTAIxxxxxxxxxxxxxxxx"
export Ali_Secret="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

可以用下面命令检查变量是否已经设置:

echo $Ali_Key
echo $Ali_Secret

但不要截图或公开输出 Secret。


8. 申请泛域名证书

执行:

~/.acme.sh/acme.sh --issue \
  --dns dns_ali \
  -d snowmoon1824.top \
  -d "*.snowmoon1824.top"

参数解释:

参数作用
--issue申请证书
--dns dns_ali使用阿里云 DNS API 进行 DNS-01 验证
-d snowmoon1824.top申请主域名证书
-d "*.snowmoon1824.top"申请泛域名证书
引号防止 Shell 把 * 当通配符展开

成功后会看到类似:

Cert success.
Your cert is in: /root/.acme.sh/snowmoon1824.top_ecc/snowmoon1824.top.cer
Your cert key is in: /root/.acme.sh/snowmoon1824.top_ecc/snowmoon1824.top.key
The full-chain cert is in: /root/.acme.sh/snowmoon1824.top_ecc/fullchain.cer

这里出现:

snowmoon1824.top_ecc

说明签发的是 ECC 证书。

后续安装证书时需要加:

--ecc

9. 为什么不要直接使用 /root/.acme.sh/ 里的证书?

acme.sh 原始证书路径类似:

/root/.acme.sh/snowmoon1824.top_ecc/

不建议让 Nginx 或宝塔面板直接引用这里的文件。

原因:

  1. 这是 acme.sh 的内部管理目录;
  2. 结构可能受 acme.sh 自身影响;
  3. 直接引用不利于统一管理;
  4. 以后迁移或排查不清晰。

因此创建一个统一证书目录:

/etc/nginx/ssl/snowmoon1824.top/

普通网站都统一使用这里的证书。


10. 安装证书到统一 Nginx SSL 目录

先创建目录:

mkdir -p /etc/nginx/ssl/snowmoon1824.top

然后执行:

~/.acme.sh/acme.sh --install-cert \
  -d snowmoon1824.top \
  --ecc \
  --key-file /etc/nginx/ssl/snowmoon1824.top/key.pem \
  --fullchain-file /etc/nginx/ssl/snowmoon1824.top/fullchain.pem \
  --reloadcmd "/etc/init.d/nginx reload"

参数解释:

参数作用
--install-cert安装证书到指定路径
-d snowmoon1824.top指定使用哪张证书
--ecc指定使用 ECC 证书
--key-file私钥安装路径
--fullchain-file完整证书链安装路径
--reloadcmd续签后自动执行的重载命令

安装后检查:

ls -l /etc/nginx/ssl/snowmoon1824.top

应该能看到:

fullchain.pem
key.pem

11. 给 blog.snowmoon1824.top 配置 SSL

11.1 站点配置文件位置

宝塔 Nginx 站点配置目录:

/www/server/panel/vhost/nginx/

查看配置文件:

ls /www/server/panel/vhost/nginx/

本次站点配置文件为:

/www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

11.2 先备份配置文件

修改前先备份:

cp /www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf \
/www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf.bak

原因:

Nginx 配置一旦改错,可能导致整个 Nginx reload 失败。
备份可以在出错时快速恢复。

11.3 检查是否已有 SSL 配置

执行:

grep -n "ssl_certificate" /www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

如果没有输出,说明宝塔还没有为这个站点生成 HTTPS 配置。

这种情况下,不建议手写完整 443 server 配置。
更稳的做法是:

先在宝塔面板里启用一次 SSL
让宝塔自动生成 listen 443 ssl、rewrite、PHP、日志等相关配置
然后再把证书路径替换成统一路径

11.4 在宝塔面板中启用 SSL

进入:

宝塔面板
→ 网站
→ blog.snowmoon1824.top
→ SSL
→ 其他证书

注意,宝塔输入框里不能填:

cat /etc/nginx/ssl/snowmoon1824.top/key.pem

因为这是命令,不是证书内容。

正确做法是先在 SSH 终端执行:

cat /etc/nginx/ssl/snowmoon1824.top/key.pem

复制完整输出,粘贴到宝塔的:

密钥(KEY)

私钥内容类似:

-----BEGIN EC PRIVATE KEY-----
...
-----END EC PRIVATE KEY-----

或者:

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

再执行:

cat /etc/nginx/ssl/snowmoon1824.top/fullchain.pem

复制完整输出,粘贴到宝塔的:

证书(PEM格式)

证书内容类似:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

然后点击:

保存并启用证书

可以顺便开启:

强制 HTTPS

11.5 替换 blog 的 SSL 路径

宝塔生成 SSL 配置后,再执行:

grep -n "ssl_certificate" /www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

如果能看到类似:

ssl_certificate    /www/server/panel/vhost/cert/blog.snowmoon1824.top/fullchain.pem;
ssl_certificate_key    /www/server/panel/vhost/cert/blog.snowmoon1824.top/privkey.pem;

说明宝塔已经生成了 SSL 配置。

接下来替换成统一证书路径:

sed -i 's#ssl_certificate .*;#ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;#' \
/www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf
sed -i 's#ssl_certificate_key .*;#ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;#' \
/www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

再次检查:

grep -n "ssl_certificate" /www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

理想结果:

ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;

这样做的原因是:

blog.snowmoon1824.top 不再使用宝塔复制出来的证书副本,
而是直接使用 acme.sh 自动续签后更新的统一证书路径。

11.6 检查并重载 Nginx

检查配置:

/www/server/nginx/sbin/nginx -t

如果输出:

syntax is ok
test is successful

再重载 Nginx:

/etc/init.d/nginx reload

不要在 nginx -t 报错时 reload。


12. 宝塔面板登录地址 bt.snowmoon1824.top 的 SSL 配置

12.1 判断 bt.snowmoon1824.top 的性质

bt.snowmoon1824.top 是宝塔面板登录地址,不是普通网站。

因此它不走:

/www/server/panel/vhost/nginx/bt.snowmoon1824.top.conf

而是使用宝塔面板自身 SSL 目录:

/www/server/panel/ssl/

12.2 确认宝塔面板 SSL 文件

执行:

ls -l /www/server/panel/ssl/

本次看到的关键文件为:

certificate.pem
privateKey.pem

这两个文件分别是:

文件作用
certificate.pem宝塔面板使用的证书
privateKey.pem宝塔面板使用的私钥

13. 创建统一部署脚本

为了让普通网站和宝塔面板都自动使用新证书,创建统一部署脚本:

nano /root/deploy_snowmoon_ssl.sh

写入:

#!/bin/bash
set -e

DOMAIN="snowmoon1824.top"

NGINX_SSL_DIR="/etc/nginx/ssl/$DOMAIN"
BT_PANEL_SSL_DIR="/www/server/panel/ssl"

# 1. 检查普通网站统一证书是否存在
if [ ! -f "$NGINX_SSL_DIR/fullchain.pem" ]; then
  echo "ERROR: Missing $NGINX_SSL_DIR/fullchain.pem"
  exit 1
fi

if [ ! -f "$NGINX_SSL_DIR/key.pem" ]; then
  echo "ERROR: Missing $NGINX_SSL_DIR/key.pem"
  exit 1
fi

# 2. 部署到宝塔面板 SSL 目录
mkdir -p "$BT_PANEL_SSL_DIR"

cp "$NGINX_SSL_DIR/fullchain.pem" "$BT_PANEL_SSL_DIR/certificate.pem"
cp "$NGINX_SSL_DIR/key.pem" "$BT_PANEL_SSL_DIR/privateKey.pem"

chmod 644 "$BT_PANEL_SSL_DIR/certificate.pem"
chmod 600 "$BT_PANEL_SSL_DIR/privateKey.pem"

# 3. 检查并重载 Nginx
if [ -x /www/server/nginx/sbin/nginx ]; then
  /www/server/nginx/sbin/nginx -t && /etc/init.d/nginx reload
elif command -v nginx >/dev/null 2>&1; then
  nginx -t && nginx -s reload
fi

# 4. 重启宝塔面板,让 bt.snowmoon1824.top 使用新证书
if command -v bt >/dev/null 2>&1; then
  bt restart
else
  echo "WARNING: bt command not found, panel not restarted."
fi

echo "SSL deployed successfully for $DOMAIN"

保存后赋予执行权限:

chmod +x /root/deploy_snowmoon_ssl.sh

手动运行一次:

/root/deploy_snowmoon_ssl.sh

如果看到 Nginx 配置检查成功、Nginx reload 成功、宝塔面板重启成功,说明脚本正常。

运行脚本时,宝塔终端可能会断开连接,这是因为执行了:

bt restart

属于正常现象。等待重新连接即可。


14. 为什么需要统一部署脚本?

只配置:

--reloadcmd "/etc/init.d/nginx reload"

只能让 Nginx 加载新证书。

但宝塔面板登录地址 bt.snowmoon1824.top 使用的是:

/www/server/panel/ssl/certificate.pem
/www/server/panel/ssl/privateKey.pem

它不会自动读取:

/etc/nginx/ssl/snowmoon1824.top/fullchain.pem
/etc/nginx/ssl/snowmoon1824.top/key.pem

所以需要脚本同步证书:

/etc/nginx/ssl/snowmoon1824.top/
→ /www/server/panel/ssl/

并重启宝塔面板:

bt restart

这样 bt.snowmoon1824.top 才会自动使用新证书。


15. 绑定 acme.sh 续签后的自动部署命令

执行:

~/.acme.sh/acme.sh --install-cert \
  -d snowmoon1824.top \
  --ecc \
  --key-file /etc/nginx/ssl/snowmoon1824.top/key.pem \
  --fullchain-file /etc/nginx/ssl/snowmoon1824.top/fullchain.pem \
  --reloadcmd "/root/deploy_snowmoon_ssl.sh"

这一步非常关键。

它的作用是:

告诉 acme.sh:
以后这张证书续签成功后,
先把证书安装到 /etc/nginx/ssl/snowmoon1824.top/,
然后执行 /root/deploy_snowmoon_ssl.sh。

最终自动流程变成:

acme.sh 自动续签
→ 更新 /etc/nginx/ssl/snowmoon1824.top/key.pem
→ 更新 /etc/nginx/ssl/snowmoon1824.top/fullchain.pem
→ 执行 /root/deploy_snowmoon_ssl.sh
→ 同步到宝塔面板 SSL 目录
→ reload Nginx
→ restart 宝塔面板

16. 检查 acme.sh 自动续签任务

执行:

crontab -l

可以看到类似:

45 5 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

这说明 acme.sh 的自动续签任务已经存在。

注意:

它不是每天重新申请证书。
它是每天检查证书是否需要续签。
只有接近续签窗口时才会真正续签。

17. 检查 acme.sh 是否记录了正确安装路径和部署命令

执行:

cat /root/.acme.sh/snowmoon1824.top_ecc/snowmoon1824.top.conf | grep -E "Le_RealKeyPath|Le_RealFullChainPath|Le_ReloadCmd"

理想输出类似:

Le_RealKeyPath='/etc/nginx/ssl/snowmoon1824.top/key.pem'
Le_ReloadCmd='__ACME_BASE64__...'
Le_RealFullChainPath='/etc/nginx/ssl/snowmoon1824.top/fullchain.pem'

其中:

字段含义
Le_RealKeyPath私钥安装路径
Le_RealFullChainPath完整证书链安装路径
Le_ReloadCmd续签后执行的命令

Le_ReloadCmd 显示为:

__ACME_BASE64__...

是正常现象,表示命令被 acme.sh 编码保存了。

只要它存在,就说明续签后会执行对应部署命令。


18. 最终完成状态

当前最终状态为:

项目状态
阿里云 RAM 用户已创建
AccessKey ID / Secret已配置
RAM DNS 权限已授权
acme.sh已安装
默认 CA已设置为 Let’s Encrypt
泛域名证书已签发
DNS-01 自动验证已成功
统一证书路径已建立
blog 站点 SSL已配置
blog 使用统一证书路径已完成
宝塔面板 SSL 目录已确认
部署脚本已创建
部署脚本手动运行已成功
acme.sh 自动续签 cron已存在
acme.sh 续签后自动执行部署脚本已配置

最终链路:

Let’s Encrypt 泛域名证书
→ acme.sh 自动续签
→ 阿里云 DNS API 自动验证
→ /etc/nginx/ssl/snowmoon1824.top/ 自动更新
→ blog.snowmoon1824.top 自动使用新证书
→ /root/deploy_snowmoon_ssl.sh 自动执行
→ 宝塔面板 SSL 自动同步
→ bt.snowmoon1824.top 自动使用新证书

19. 以后新增网站应该怎么做?

以后新增一级子域名网站,例如:

nav.snowmoon1824.top
api.snowmoon1824.top
alist.snowmoon1824.top

不需要重新申请证书。

因为当前证书已经覆盖:

*.snowmoon1824.top

19.1 第一步:DNS 解析

如果已经在阿里云 DNS 添加了泛解析:

主机记录:*
记录类型:A
记录值:服务器公网 IP

那么以后新增一级子域名时,一般不需要额外添加 DNS 记录。

如果没有泛解析,就需要单独添加,例如:

主机记录:nav
记录类型:A
记录值:服务器公网 IP

建议添加泛解析:

*  A  服务器公网 IP

好处:

新增任何一级子域名时,DNS 自动指向服务器。

风险:

所有未单独配置的子域名也会解析到服务器。

19.2 第二步:宝塔添加站点

在宝塔面板中:

网站
→ 添加站点
→ 填写新域名

例如:

nav.snowmoon1824.top

网站根目录可以设为:

/www/wwwroot/nav.snowmoon1824.top

19.3 第三步:先让宝塔生成 SSL 配置

进入:

网站
→ nav.snowmoon1824.top
→ SSL
→ 其他证书

粘贴已有统一证书内容。

私钥内容:

cat /etc/nginx/ssl/snowmoon1824.top/key.pem

证书内容:

cat /etc/nginx/ssl/snowmoon1824.top/fullchain.pem

保存并启用证书。

这么做的原因是:

让宝塔自动生成完整的 HTTPS server 配置,
避免手写 listen 443 ssl、rewrite、PHP、日志配置时出错。

19.4 第四步:把新站点证书路径改成统一路径

假设新站点是:

nav.snowmoon1824.top

配置文件是:

/www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf

先备份:

cp /www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf \
/www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf.bak

替换路径:

sed -i 's#ssl_certificate .*;#ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;#' \
/www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf
sed -i 's#ssl_certificate_key .*;#ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;#' \
/www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf

检查:

grep -n "ssl_certificate" /www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf

理想结果:

ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;

检查 Nginx:

/www/server/nginx/sbin/nginx -t

成功后重载:

/etc/init.d/nginx reload

19.5 新增网站标准流程总结

以后每新增一个网站:

1. 确认 DNS 解析
2. 宝塔添加站点
3. 宝塔 SSL → 其他证书 → 粘贴当前泛域名证书
4. 保存并启用,让宝塔生成 HTTPS 配置
5. 备份站点 conf 文件
6. 把 ssl_certificate 路径改成统一路径
7. nginx -t 检查
8. reload Nginx

统一证书路径固定为:

ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;

20. 注意事项

20.1 不要在宝塔里重新申请 SSL

对于已经接入统一证书路径的网站,不要随便在宝塔里点击:

申请证书
重新部署证书
保存新的 SSL 证书

否则宝塔可能会把配置改回自己的证书路径,例如:

/www/server/panel/vhost/cert/站点名/fullchain.pem

这样会导致:

acme.sh 自动续签后的新证书不会被该网站使用。

20.2 新网站第一次仍然需要配置一次

统一部署脚本只能负责:

续签后更新证书文件
reload Nginx
同步宝塔面板 SSL
restart 宝塔面板

它不能自动让一个新网站知道自己应该使用哪张证书。

因此新网站第一次仍然要配置一次:

ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;

配置完成后,后续就不需要手动换证书了。


20.3 不要泄露 AccessKey

阿里云 RAM 用户的 AccessKey 可以操作 DNS 解析。

如果泄露,别人可能:

修改你的 DNS 记录
劫持你的域名解析
破坏证书续签

因此:

  • 不要截图;
  • 不要发给别人;
  • 不要上传到 GitHub;
  • 不要写进公开博客;
  • 如果怀疑泄露,立即禁用或删除 AccessKey。

20.4 RAM 用户权限不要过大

建议只给 DNS 权限,例如:

AliyunDNSFullAccess

不要给:

AdministratorAccess

原因是最小权限原则。

即使这个 RAM 用户的 AccessKey 泄露,影响范围也限制在 DNS。


20.5 *.snowmoon1824.top 只覆盖一级子域名

可以覆盖:

blog.snowmoon1824.top
bt.snowmoon1824.top
api.snowmoon1824.top
www.snowmoon1824.top

不能覆盖:

a.b.snowmoon1824.top
test.api.snowmoon1824.top

如果将来需要覆盖:

*.api.snowmoon1824.top

需要额外申请:

-d "*.api.snowmoon1824.top"

20.6 修改 Nginx 配置前一定备份

每次改站点配置前,先执行:

cp 原配置文件 原配置文件.bak

例如:

cp /www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf \
/www/server/panel/vhost/nginx/nav.snowmoon1824.top.conf.bak

原因:

如果 sed 替换错了,或者配置被破坏,可以快速恢复。

20.7 reload 前一定先 nginx -t

每次改完 Nginx 配置后,都要先执行:

/www/server/nginx/sbin/nginx -t

只有出现:

syntax is ok
test is successful

才能执行:

/etc/init.d/nginx reload

不要在 Nginx 配置测试失败时 reload。


20.8 宝塔面板重启会导致短暂断开

统一部署脚本中包含:

bt restart

因此执行脚本时,宝塔面板或宝塔终端可能会短暂断开。

这是正常现象。

等待 10-30 秒后重新访问即可。


20.9 浏览器可能缓存旧证书

刚换完证书后,如果浏览器显示的还是旧证书,可以尝试:

无痕窗口
清理浏览器缓存
等待几分钟
换一个浏览器测试

20.10 证书续签不是每天都会发生

crontab 中的 acme.sh 任务每天运行,但它只是检查证书是否需要续签。

它不会每天重新申请证书。

证书接近续签窗口时,acme.sh 才会真正续签。


21. 常用检查命令

查看 acme.sh 证书列表

~/.acme.sh/acme.sh --list

查看自动续签任务

crontab -l

查看证书安装路径和 reload 命令

cat /root/.acme.sh/snowmoon1824.top_ecc/snowmoon1824.top.conf | grep -E "Le_RealKeyPath|Le_RealFullChainPath|Le_ReloadCmd"

查看 blog 是否使用统一证书路径

grep -n "ssl_certificate" /www/server/panel/vhost/nginx/blog.snowmoon1824.top.conf

检查 Nginx 配置

/www/server/nginx/sbin/nginx -t

重载 Nginx

/etc/init.d/nginx reload

查看统一证书目录

ls -l /etc/nginx/ssl/snowmoon1824.top

查看宝塔面板 SSL 目录

ls -l /www/server/panel/ssl/

手动执行统一部署脚本

/root/deploy_snowmoon_ssl.sh

22. 故障排查

22.1 报错:You don't specify aliyun api key and secret yet

原因:

acme.sh 没有读取到 Ali_Key 和 Ali_Secret。

解决:

export Ali_Key="你的AccessKey_ID"
export Ali_Secret="你的AccessKey_Secret"

注意变量名必须是:

Ali_Key
Ali_Secret

不是:

ALI_KEY
ALI_SECRET
AccessKey
AccessKeySecret

22.2 报错:Error adding TXT record

可能原因:

RAM 用户没有 DNS 权限
AccessKey 错误
域名 DNS 不在阿里云托管
阿里云 API 调用失败

处理:

检查 RAM 用户是否有 AliyunDNSFullAccess
检查 AccessKey 是否正确
确认域名解析托管在阿里云 DNS

22.3 宝塔提示“私钥错误”

常见原因:

把 cat 命令本身粘贴进了宝塔输入框
而不是粘贴 key.pem 文件内容

错误:

cat /etc/nginx/ssl/snowmoon1824.top/key.pem

正确:

-----BEGIN EC PRIVATE KEY-----
...
-----END EC PRIVATE KEY-----

22.4 grep 没有 ssl_certificate 输出

说明该站点还没有启用 SSL,宝塔还没有生成 HTTPS 配置。

处理:

先在宝塔 SSL 页面使用“其他证书”启用一次 SSL,
让宝塔生成 443 配置,
然后再替换证书路径。

22.5 Nginx reload 失败

先执行:

/www/server/nginx/sbin/nginx -t

根据错误信息处理。

常见原因:

证书路径不存在
私钥路径不存在
配置语法错误
server 块写错
端口冲突

23. 最终结论

通过这套方案,已经实现:

免费 SSL
泛域名证书
阿里云 DNS API 自动验证
acme.sh 自动续签
Nginx 自动使用新证书
宝塔面板登录地址自动使用新证书
新增一级子域名可复用同一张证书

最终需要长期记住的核心路径是:

/etc/nginx/ssl/snowmoon1824.top/fullchain.pem
/etc/nginx/ssl/snowmoon1824.top/key.pem

普通网站统一引用:

ssl_certificate /etc/nginx/ssl/snowmoon1824.top/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/snowmoon1824.top/key.pem;

宝塔面板自动同步到:

/www/server/panel/ssl/certificate.pem
/www/server/panel/ssl/privateKey.pem

以后新增网站时,不需要重新申请证书,只需要让新网站引用统一证书路径即可。

此作者没有提供个人介绍。
最后更新于 2026-06-01