Git Bash + acme.sh 实现 SSL 证书自动续签(完整指南)

适用环境:Windows 腾讯云主机 + 域名解析在阿里云 + Nginx 证书类型:Let's Encrypt 免费 DV 证书(有效期 90 天,自动续签) 验证方式:DNS-01(阿里云 DNS API 自动添加 TXT 记录,不占用 80 端口)


目录


一、整体思路(先搞懂在做什么)

自动续签这件事,本质是 4 个环节串起来,缺一个都不算"自动":

环节 谁负责 作用
① 终端环境 Git Bash 提供类 Linux 的 Bash 环境,让 acme.sh 脚本能跑起来
② 签发工具 acme.sh 向 Let's Encrypt 申请/续签证书,通过 DNS API 自动验证域名归属
③ 域名验证 阿里云 DNS (dns_ali 插件) 自动添加/删除 _acme-challenge 的 TXT 记录,证明"这域名是你的"
④ 定时触发 Windows 计划任务 acme.sh.cron 每天跑一次 --cron,到期才续,不到期就跳过

关键认知:

  • 主机在腾讯云 ≠ 用腾讯云 DNS 。DNS 验证看的是"域名解析记录在哪一家"------解析在阿里云,就必须用 dns_ali 插件。

  • 计划任务只决定"多久检查一次",真正决定"多久续一次"的是 acme.sh 内部判断(证书剩余 < 30 天才续)。

  • 证书文件替换不是计划任务直接复制,而是 acme.sh 续签成功后,按 --install-cert 时记录的路径自动覆盖 + 执行 reload。


二、安装 Git(提供 Bash 环境)

acme.sh 是一个 Shell 脚本,必须在 Bash 环境下运行,Windows 本身没有,所以需要装 Git for Windows。

2.1 安装过程中的关键选项

安装界面 正确选择 说明
默认编辑器 Use Visual Studio Code / Notepad 不要选 Vim(新手容易卡在里面出不来)
PATH 环境 Git from the command line and also from 3rd-party software 让 CMD/PowerShell/VS Code 都能识别 git
SSH 客户端 Use bundled OpenSSH 自带、独立、不冲突
HTTPS 后端 Use the OpenSSL library 个人环境最稳,不受系统证书更新干扰
换行符转换 Checkout Windows-style, commit Unix-style Windows 官方推荐默认项
终端模拟器 Use MinTTY 复制粘贴方便、中文不乱码
git pull 行为 Merge(默认) 最安全直观
额外选项 勾选 Enable file system caching 提升运行速度;符号链接不用勾

2.2 验证安装

安装完成后,右键菜单选 Git Bash Here,执行:

复制代码
git --version

输出类似 git version 2.56.0.windows.2 即成功。


三、安装 acme.sh

国内云主机直连 GitHub 经常超时或被重置,改用国内 Gitee 镜像 用 git clone 安装。

3.1 安装命令

复制代码
# 1. 清理可能失败的残留
rm -rf acme.sh
​
# 2. 用国内 Gitee 镜像拉取(官方镜像较旧,用此同步镜像)
git clone https://gitee.com/wenber/acme.sh.git
​
# 3. 进入目录
cd acme.sh
​
# 4. 执行安装(把邮箱换成你自己的)
./acme.sh --install -m your@email.com

3.2 关于"输入 Windows 密码"

安装过程中如果出现:

复制代码
Please input your Windows password for: Administrator

这是正常的! 表示 acme.sh 正在尝试创建 Windows 计划任务(用于自动续签),需要管理员权限验证身份。

  • 正确做法:输入 Administrator 账号的登录密码,回车。

  • 不要 按 Ctrl + C 终止,否则计划任务建不起来,自动续签就废了。

安装过程中出现的 socat 缺失警告可以直接忽略,用 DNS 验证方式不需要它。

3.3 让配置生效并验证

安装完成后关闭 Git Bash,重新打开,执行:

复制代码
~/.acme.sh/acme.sh --version

能显示版本号即安装成功。

重要 :以后所有 acme.sh 命令都用 ~/.acme.sh/acme.sh 绝对路径调用,最稳,不受 alias 是否生效影响。


四、获取阿里云 RAM 子账号密钥

因为域名解析在阿里云,要用 dns_ali 插件,需要阿里云的 API 密钥来自动操作 DNS 记录。

4.1 创建 RAM 子账号(不要用主账号!)

  1. 登录阿里云控制台 → 访问控制 RAM

  2. 创建用户 → 勾选「OpenAPI 调用」

  3. 授权策略:

    • 省事:AliyunDNSFullAccess

    • 更严谨:只授予「云解析 DNS」的写记录权限

  4. 创建后拿到一对:AccessKey ID 和 AccessKey Secret

4.2 ⚠️ 安全铁律

  • 永远不要在聊天记录、截图、日志、GitHub 里贴出你的 AccessKey Secret。

  • 一旦泄露,立即去 RAM 控制台禁用并删除该 AccessKey,重新建一对。

  • 建议用子账号密钥,权限最小化,即使泄露影响范围也有限。


五、签发证书

5.1 注入密钥(注意变量名!)

dns_ali 插件只读 Ali_Key 和 Ali_Secret ,用错变量名会报 You don't specify aliyun api key and secret yet。

复制代码
export Ali_Key="你的AccessKeyId"
export Ali_Secret="你的AccessKeySecret"

常见错误:把变量名写成 Tencent_SecretId / Tencent_SecretKey。那是腾讯云插件的变量名,用 dns_ali 时不认。

5.2 设置默认 CA

复制代码
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

5.3 签发

复制代码
~/.acme.sh/acme.sh --issue -d ai.dql5251.top --dns dns_ali
  • 要带 www:追加 -d www.dql5251.top

  • 要通配符:-d '*.dql5251.top'

5.4 成功标志

看到以下输出即成功:

复制代码
Success
Cert success.
-----BEGIN CERTIFICATE-----

证书文件位于:~/.acme.sh/ai.dql5251.top_ecc/ 目录下。

5.5 关于过程中的红色错误行

签发日志里可能出现红色字体的 curl error code: 35、28 等,例如:

复制代码
Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: 35
Please refer to ... for error code: 28
Sleeping for 20 seconds first

这不是报错,不用管。 这是 acme.sh 用 curl 检查 DNS 解析是否生效时遇到的网络抖动:

  • Error 28:连接超时

  • Error 35:SSL/TLS 握手失败

acme.sh 有自动重试机制 ,会休眠 20 秒后换公共 DNS 再查。只要后面出现 All checks succeeded 和 Success,就说明重试后已顺利拿到证书。


六、部署证书到 Nginx

签发成功后,需要把证书"部署"到 Nginx 使用的路径,并让 acme.sh 记住覆盖路径 和重载命令,这样以后每次续签才能自动生效。

6.1 部署命令

假设你的 Nginx 证书目录是 C:/nginx/certs/,证书文件名为 ai.DQL5251.top-key.pem 和 ai.DQL5251.top-chain.pem:

复制代码
~/.acme.sh/acme.sh --install-cert -d ai.dql5251.top \
  --key-file  /c/nginx/certs/ai.DQL5251.top-key.pem \
  --fullchain-file /c/nginx/certs/ai.DQL5251.top-chain.pem \
  --reloadcmd "cd /c/nginx && ./nginx.exe -s reload"

路径写法注意 :在 Git Bash 里,C:/xxx 要写成 /c/xxx。

这条命令干了三件事:

  1. 把新证书复制到 Nginx 的 certs 目录(覆盖)

  2. 把这两条路径和 reload 命令记录进域名配置文件

  3. 以后每次续签成功,自动执行"覆盖 + reload"

6.2 验证 Nginx 是否生效

浏览器访问 https://ai.dql5251.top,点地址栏小锁图标,确认证书有效期已更新。


七、自动续签原理(计划任务)

7.1 acme.sh 自动创建了计划任务

acme.sh 安装时(就是让你输密码那一步)会自动在 Windows 任务计划程序里创建一个名为 acme.sh.cron 的任务:

  • 路径:任务计划程序库 → 根目录(不在子文件夹里)

  • 触发器:每天 0:12 执行

  • 操作 :调用 bash.exe -c "~/.acme.sh/acme.sh --cron --home ~/.acme.sh"

打开 taskschd.msc 就能看到它,状态为"准备就绪",说明自动续签已经就绪。

7.2 续签链路全貌

复制代码
Windows 计划任务(每天 0:12)
        │
        ▼
acme.sh --cron
        │
        ├─ 证书剩余 > 30 天 → 输出 "Skip, cert not due" → 退出(不消耗配额)
        │
        └─ 证书剩余 < 30 天 → 用 dns_ali 自动加 TXT → 续签成功
                                    │
                                    ▼
                        按 --install-cert 记录的路径覆盖证书文件
                                    │
                                    ▼
                        执行 --reloadcmd(nginx -s reload)

7.3 关于"频率"的两个误区

误解 真相
计划任务每天跑 = 每天续签一次 ❌ 计划任务每天检查一次,到期才续
需要手动写 bat 复制证书 ❌ acme.sh 内部钩子自动覆盖,计划任务不碰证书文件

八、日常检查与排错

8.1 查看证书列表和续签日期

复制代码
~/.acme.sh/acme.sh --list

输出示例:

复制代码
Main_Domain     KeyLength  SAN_Domains  CA               Created               Renew
ai.dql5251.top  "ec-256"   no           LetsEncrypt.org  2026-10-20T09:25:12Z  2026-12-18T09:25:12Z

Renew 列就是预计续签日期。

8.2 查看证书详细信息

复制代码
~/.acme.sh/acme.sh --info -d ai.dql5251.top

8.3 确认部署配置已记录

复制代码
grep -E "Le_KeyFile|Le_FullChainFile|Le_ReloadCmd" \
  ~/.acme.sh/ai.dql5251.top_ecc/ai.dql5251.top.conf

有输出 = 续签后会自动覆盖 + reload。

8.4 查看证书实际到期时间

复制代码
openssl x509 -in /c/nginx/certs/ai.DQL5251.top-chain.pem -noout -dates

8.5 手动触发一次续签检查(不强制)

复制代码
~/.acme.sh/acme.sh --cron
  • 输出 Skip / Cert not due → 正常,没到续签期

  • 输出 Renew + reload → 这次真续了

8.6 ⚠️ 别手贱反复重签

Let's Encrypt 生产环境限速:

限制项 阈值
同注册域名 50 张 / 7 天
同域名集合 5 张 / 7 天

触发后只能等,官方不手工解封。

复制代码
# ❌ 禁止反复跑,会吃配额
acme.sh --renew --force
​
# ✅ 想测试就用这个,没到 30 天直接 Skip,不消耗配额
acme.sh --cron

8.7 排错加 --debug

复制代码
~/.acme.sh/acme.sh --issue -d ai.dql5251.top --dns dns_ali --debug 2

在输出里搜 Ali_Key 看密钥有没有被正确读取。

8.8 密钥写错怎么改

如果密钥有换行、空格或拼错,检查并修正:

复制代码
# 编辑配置文件
vi ~/.acme.sh/account.conf

确保 Ali_Key 和 Ali_Secret 的值没有多余字符。


九、常见问题 FAQ

Q1:为什么 acme.sh: command not found?

A :安装时按了 Ctrl+C 或密码没输对,导致安装没跑完。用绝对路径 ~/.acme.sh/acme.sh 重试;还是不行就按第三章重装一次(别加 --no-cron)。

Q2:为什么报 You don't specify aliyun api key and secret yet?

A :变量名写错了。dns_ali 插件只读 Ali_Key / Ali_Secret,不认 Tencent_* 或其他名字。

Q3:schtasks /query 报 无效参数/选项 - 'C:/Program Files/Git/query'?

A :schtasks 是 Windows 原生命令,不能在 Git Bash 里跑 (Bash 会把 /tn 转成路径)。要么在图形界面看,要么用管理员 PowerShell / CMD 执行。

Q4:计划任务名字为什么叫 acme.sh.cron 而不是我设的名字?

A :这是 acme.sh 官方安装时自动创建的名字,直接用就好。截图里那个 win-acme renew 是另一款工具建的,跟你无关。

Q5:签发日志里的红色 curl 错误要管吗?

A :不用。那是 DNS 检查的网络抖动,acme.sh 会自动重试。只要最后出现 Success 和 -----BEGIN CERTIFICATE----- 就成功了。

Q6:证书文件到底是谁复制的?

A :是 acme.sh 内部部署钩子(--install-cert 时记录的路径),不是计划任务,也不是你手动 copy。


十、安全提醒

  1. AccessKey 是最高敏感凭证,一旦在任何公开场合泄露,立刻去阿里云 RAM 控制台禁用删除并重建。

  2. 永远用 RAM 子账号,权限只开「云解析 DNS」,不用主账号密钥。

  3. 别把 Secret 写进会被提交的脚本或日志 。--install-cert 之后 acme.sh 会把密钥加密存进配置,一般不用重复 export。

  4. 别用 --force 反复续签,会触发 Let's Encrypt 限速,导致 7 天内无法再签发。


附录:最终状态清单

  • 证书:Let's Encrypt,有效期 90 天

  • 验证方式:阿里云 DNS API (dns_ali),自动加 TXT,不占 80 端口

  • 部署路径:C:/nginx/certs/,nginx.conf 无需改动

  • 续签触发:Windows 计划任务 acme.sh.cron,每天 0:12

  • 续签判断:证书剩余 < 30 天

  • 生效方式:自动覆盖证书文件 + nginx -s reload

  • 人工介入:0

一句话总结:装好 Git → 装好 acme.sh(输密码别跳过)→ 配好阿里云 DNS 密钥 → 签发 → 部署到 Nginx → 计划任务已自动建好 → 从此不用再管。

相关推荐
nunumaymax6 小时前
Git教程
git
Brilliantwxx7 小时前
【Linux】基础IO(下):输出重定向、dup2 与 minishell 重定向实战
linux·运维·服务器·github·bash
阿萨德528号7 小时前
IDEA 项目 SVN 配置消失、版本控制变成 Git 且无 VCS 菜单的解决办法
git·svn·intellij-idea
R²AIN SUITE9 小时前
项目管理平台怎么和OA、钉钉、飞书、Git仓库打通?从消息通知到双向同步的5种实现路径
git·钉钉·飞书
Demons_kirit21 小时前
CTFHub 信息泄露通关笔记:Git泄露 Log - 教程
笔记·git·网络安全
鬼手点金1 天前
构建有效 Agent 的核心原则
java·人工智能·git·学习·自动化
索西引擎1 天前
Git 大文件阻断推送的成因与历史重写修复
git
csdn2015_1 天前
git 合并分支
大数据·git·elasticsearch