Windows下Let‘s Encrypt证书自动续期实战:win-acme+阿里云DNS+宝塔面板
2026/9/16 1:11:41 网站建设 项目流程

1. 先说痛点:这 90 天的倒计时,到底烦在哪

做过网站运维的人都有体会,Let's Encrypt 这种免费证书虽然不花钱,但有效期只有 90 天。这意味着你每年至少得手动折腾四次:登录服务器、跑一次申请脚本、把新证书文件复制到宝塔对应的站点目录、再重载一遍 Nginx 或 Apache。运气好五分钟搞定,运气不好碰上证书链没更新、文件权限不对、宝塔面板缓存没刷新,半小时就没了。

如果是单个站点还好,一旦服务器上挂了十几个域名,那这个重复劳动就变成了每个月都要惦记的定时任务。而且最容易出问题的恰恰不是申请证书本身,而是“人”这个环节——出差忘了、周末不想开电脑、过年放假直接错过续期日期。等收到浏览器大红叉报警的时候,才发现证书已经过期一两天了,访客流失和信任损失已经造成。

我试过好几套自动化方案,最终稳定运行了一年的组合是:Windows Server + 宝塔面板 + win-acme + 阿里云 DNS 验证。这个方案完全免费,全程无需人工干预,续期完成后还能自动把新证书部署到宝塔站点上。文章就把完整流程拆开讲清楚,适合正在用 Windows 服务器建站、手里域名托管在阿里云、又被 90 天续期搞得头大的朋友直接照着抄。

需要说明的是,这套流程基于我实际维护的两台 Windows Server 2019 服务器写出来的,宝塔版本是 7.x,win-acme 用的是 v2.x 分支。版本不同菜单名称可能略有差异,但原理完全一致。

2. 方案选型:为什么是 win-acme + 阿里云 DNS,而不是别的路子

2.1 先弄明白自动续期的几个关键环节

证书自动续期听起来高大上,拆开看就三个环节:域名所有权验证、证书签发/续期、证书替换与生效。Let's Encrypt 这类 ACME 协议的服务商,本质上只关心一个问题——你怎么证明自己拥有这个域名。

验证方式主流有两种。HTTP 验证是在网站根目录放一个随机 token 文件,CA 服务商通过 HTTP 访问这个文件来确认域名控制权。这种方式最简单,但要求 80 端口对外开放、Web 服务正常运行。DNS 验证则是让域名增加一条指定的 TXT 解析记录,CA 去查询这条记录是否匹配。DNS 验证的优势很明显:不需要占用端口、对服务器网络环境没有任何要求,还能签发通配符证书。

win-acme 是 Windows 平台上最成熟的 ACME 客户端,它不但支持上面两种验证方式,更重要的是内置了阿里云 DNS 插件。这意味着 win-acme 可以调用阿里云 API 自动添加、自动删除 TXT 记录,把“验证”这个环节完全自动化。续期流程就变成了:计划任务触发 win-acme → win-acme 判断证书剩余天数 → 调用阿里云 API 添加解析记录 → CA 验证通过 → 签发新证书 → 执行部署脚本更新宝塔站点配置。全程不需要人碰服务器。

2.2 对比过哪些替代方案

先说宝塔自带的 Let's Encrypt 自动续期。宝塔面板确实提供了“自动续期”开关,但它依赖一条/www/server/panel/class/acme_v2.py或类似脚本配合计划任务运行,本质上还是跑 ACME 客户端。实际用下来有几个别扭的地方:一是宝塔的续期脚本对 Windows 版支持一直不算稳定,部分版本出现过续期成功后证书没更新的问题;二是宝塔的自动续期主要是配合它自己申请的域名使用,如果证书是在别处申请的,没法直接纳管;三是宝塔续期脚本出问题时的日志排查路径不透明,对有一定定制需求的场景不够灵活。

还有 Acme.sh 的 Windows 移植版和 Certbot Windows 版。Certbot 原生支持 Windows,但官方推荐用 Docker 或者 WSL 跑,对不想引入额外运行时的用户不够友好。Acme.sh 本质上是 Bash 脚本,Windows 上要用 Git Bash 或 WSL 来跑,计划任务配置也要绕一圈。win-acme 是原生的 .NET 程序,双击就能跑,和 Windows 服务、计划任务的集成天然顺滑,配一下命令行参数就能实现“无人值守”。

2.3 阿里云 DNS 在这个方案里的角色

阿里云 DNS 在这个架构里不只是域名解析服务,更准确说它是一个“可编程的验证入口”。win-acme 通过阿里云开放 API 拿到 AccessKey 后,能在十几秒内完成 TXT 记录的增删,整个过程隐蔽、快速、不干扰正式解析记录。

选择阿里云还有一个非常现实的理由:国内大量站长的域名 ICP 备案和解析都在阿里云完成,DNS 服务器用的就是阿里云解析。如果你的域名不在阿里云,只要 DNS 托管在阿里云也能用同样的方法,前提是你把域名的 NS 记录改到阿里云解析。如果你用的是 DNSPod、Cloudflare 等其他服务商,win-acme 也有对应的插件可选,原理完全一致,只是 API 调用地址和参数名不同。

3. 部署前准备:环境检查与阿里云 API 密钥申请

3.1 服务器环境确认清单

动手之前先把环境梳理一遍,这一步能避免后面很多“莫名其妙的问题”。我建议照下面这个清单逐项确认:

  • Windows 版本:Windows Server 2016/2019/2022 或 Win10/11 长期运行均可,要求能安装 .NET Framework 4.7.2 或更高版本
  • 宝塔面板:Windows 版宝塔,我用的是 7.6 版本;Windows 版宝塔和 Linux 版在计划任务、证书存放路径上有差异,下文会按 Windows 版的实际路径来写
  • Web 服务器:Nginx 或 Apache,通过宝塔安装,确认 443 端口正常、站点已经能用 HTTP 访问
  • 域名托管:域名在阿里云控制台可见,DNS 解析服务器为阿里云默认分配的 NS 地址
  • 网络环境:服务器能正常访问外网,不需要特殊代理(win-acme 默认走系统代理设置)

有一个常见误区需要提醒:很多人以为申请证书必须先把站点搭好、能通过 HTTPS 访问才能操作。实际上用 DNS 验证方式根本不要求 80/443 端口通,只要域名解析在阿里云、AccessKey 权限正确,哪怕服务器上前置了防火墙只放行远程桌面端口,也能正常签下证书。

3.2 创建阿里云 RAM 子用户并授权

阿里云的 AccessKey 不能直接用主账号的,风险太大了。主账号 AccessKey 拥有账号下所有资源的管理权限,一旦泄露等于把整个云账号拱手让人。正确做法是创建一个 RAM 子用户,只给他 DNS 解析的增删改查权限。

操作路径:登录阿里云控制台 → 鼠标悬停右上角头像 → 点击“RAM 访问控制” → 左侧菜单选择“用户” → 点击“创建用户”。

创建过程中有几个关键点:

  • 登录名填写类似win-acme-dns这样的拼音或英文名
  • 访问方式务必勾选“OpenAPI 调用访问”,这一步才会生成 AccessKey ID 和 AccessKey Secret
  • 创建完成后立即点“保存 AccessKey 信息”,页面关闭后 Secret 就不会再显示了,建议复制到临时记事本并妥善保存

用户创建好之后,进入“权限管理”页面为这个用户添加权限策略。搜索AliyunDNSFullAccess,它代表 DNS 解析的完全控制权。如果想更严谨,可以搜索AliyunDNSReadOnlyAccess这类只读权限,但 win-acme 插件需要添加和删除 TXT 记录来完成验证,所以只读权限不够用,必须给到 FullAccess。仅对 DNS 服务授权,不涉及 ECS、OSS 等其他资源,风险可控。

3.3 提前在阿里云解析中准备的记录

如果你的域名将在接下来使用通配符证书,也就是证书覆盖example.com*.example.com,阿里云解析中需要提前存在一条主域名记录,比如example.com的 A 记录指向服务器 IP。没其他特殊情况的话,大部分站点本身就已经有了这条记录。

win-acme 在申请通配符证书时,需要验证的 TXT 记录一般会长得像_acme-challenge.example.com。这条记录你不用手动创建,win-acme 插件会自动调用 API 添加。唯一要求是域名的解析权限确实在这个 AccessKey 对应的账号下。另外提醒一下,CNAME 接入到阿里云 CDN、高防等产品的域名,解析链路可能被默认记录类型干扰,遇到验证失败时优先检查这一点。

4. win-acme 安装与首次申请证书

4.1 下载与目录规划

win-acme 的官方发布地址在 GitHub 仓库的 Releases 页面,搜索win-acme releases就能找到。下载 zip 包后解压到服务器固定目录,我习惯放在C:\win-acme,路径不要带中文,不要放在用户目录的 OneDrive 同步盘里,避免权限或同步冲突。

解压后目录里有win-acme.exesettings.json和一批 DLL 文件。首次运行前不需要手动改任何配置,直接执行 exe 进入交互界面。

需要补充一个细节:win-acme 需要 .NET 环境。Windows Server 2019 默认装了 .NET 4.x,直接运行就 OK。如果你的系统是精简版或者 Server Core 没装图形界面,先装好 .NET Framework 4.8 再运行。

4.2 用交互界面完成首次证书申请

在命令行窗口进入C:\win-acme目录,运行win-acme.exe。首次启动时会询问是否创建默认设置文件,输入Y回车即可。之后会出现主菜单:

N) Create certificate (default) M) Renew certificates R) Run in interactive console ...

选择N创建新证书。接下来会问你输入域名,如果有多个域名需要写在同一个证书里,用逗号分隔,比如example.com,www.example.com。注意第一个域名会被当作主域名,证书的通用名称(CN)就用它,后续文件命名也会参考它。

接下来选择验证方式,win-acme 会列出所有可用插件。选择阿里云 DNS 插件,屏幕上大致会显示类似A) Aliyun DNS的选项。选中后会要求输入 AccessKey ID 和 AccessKey Secret,输入后确认权限校验。这里有一步非常关键:

注意:win-acme 交互界面输入 Secret 时不会显示任何字符,粘贴后直接回车即可,不要以为没输入成功。

验证方式确认完之后,win-acme 会询问证书文件的保存格式。一般选1) PEM encoded files,因为宝塔 Nginx/Apache 都直接认 PEM 格式。接下来会问是否指定文件路径,如果保持默认,证书会生成在C:\win-acme\certs\<主域名>目录下。为了后续部署方便,建议指定一个固定路径,比如C:\win-acme\certs\example.com,并在目录下生成cert.pem(全链路证书)和key.pem(私钥)两个固定名称文件。

交互界面运行完这一步,证书就已经签下来了。但真正要做的是自动化,所以下面直接讲命令行参数方式,后面会统一配置计划任务。

4.3 更推荐的方式:命令行参数一步到位

交互界面方便理解流程,但自动化部署必须用命令行参数。win-acme 的命令行参数非常丰富,我整理了一套经过验证的稳定参数组合:

C:\win-acme\win-acme.exe --renew --certificate "example.com" --validation aliyun --aliyun-access-key-id "YOUR_AK_ID" --aliyun-access-key-secret "YOUR_AK_SECRET" --store pemfiles --pemfiles-path "C:\win-acme\certs\example.com"

逐项解释一下这些参数的意义:

  • --renew:执行续期检查动作。win-acme 会先判断证书剩余天数,默认剩余 30 天以内才真正执行续期,否则直接跳过。这个参数在计划任务里和首次申请通用。
  • --certificate "example.com":目标证书名称。可以用通配符形式*.example.com作为主域名,但注意通配符域名在命令行里需要引号包住,避免被 shell 解释成通配符展开。
  • --validation aliyun:指定验证插件为阿里云 DNS。
  • --aliyun-access-key-id/--aliyun-access-key-secret:阿里云 API 密钥。直接把明文写在命令行参数里有个安全隐患——任何能看到服务器进程列表的用户都能看到密钥。更好的做法是设置环境变量ALIYUN_AK_IDALIYUN_AK_SECRET,win-acme 会优先读取环境变量。计划任务方式下,环境变量是持久化的,安全性和便捷性都更好。
  • --store pemfiles --pemfiles-path "...路径":证书以 PEM 格式保存到指定目录。

首次运行如果提示证书不存在,--renew会自动走创建流程。如果证书已经存在,会执行续期判断。这个命令用来手动测试也非常顺手,随时随地验证一遍流水线是否正常。

5. 把“自动”落地:Windows 计划任务 + 宝塔部署脚本

5.1 自动续期的触发机制设计

win-acme 续期触发有几种常见思路。第一种是把 win-acme 配置成 Windows 服务,常驻内存,由它自己每天检查续期时间;第二种是用 Windows 计划任务,每天定时跑一次win-acme.exe --renew

我更推荐第二种。原因很直接:计划任务可以精确控制执行时间(比如避开业务高峰期),而且每次执行都有日志可查,出了问题能看到完整错误栈。Windows 服务方式虽然也能用,但资源占用稍大,调试起来反而不直观。

计划任务的触发频率建议设置为“每天执行一次”,选凌晨 3-4 点。为什么不是每周一次?因为 win-acme 自己会判断剩余天数,没到续期窗口(默认 30 天内的证书)它会直接跳过,所以每天跑一次并不会带来多余的证书签发请求,反而能避免因为某天服务器维护错过了那一周的窗口。实测下来,每天跑一次的成本几乎可以忽略。

创建计划任务的步骤:

  1. 打开“任务计划程序”(Win+R 输入taskschd.msc
  2. 右侧“创建任务”,名称填win-acme-renew
  3. “常规”选项卡里勾选“不管用户是否登录都要运行”,勾选“使用最高权限运行”
  4. “触发器”选项卡新建触发器,设置为“每天”,时间选03:00
  5. “操作”选项卡新建操作:程序或脚本填C:\win-acme\win-acme.exe,参数填上面整理好的命令行参数(不含密钥明文的话,环境变量方式更稳妥)
  6. “条件”选项卡去掉“只有在计算机使用交流电源时才启动此任务”前面的勾选
  7. “设置”选项卡中勾选“如果任务失败,按以下频率重新启动”,间隔设为 10 分钟,最多重试 3 次

注意:如果你把 AccessKey 明文写进了“参数”一栏,任何有权限读取计划任务配置的账户都可能看到密钥。建议改为系统环境变量方式,然后命令行参数填--aliyun-access-key-id "%ALIYUN_AK_ID%",虽然计划任务不会自动展开环境变量,但 win-acme 本身支持从环境变量读取,直接传参数可以简化命令行的可读性。两种方式任选,我更推荐后者配合环境变量。

5.2 续期成功后的自动部署脚本

证书续下来只是第一步,怎么让宝塔的站点真正用上新证书才是关键。宝塔 Windows 版的站点证书文件路径通常长这样:

C:\www\ssl\站点名\fullchain.pem C:\www\ssl\站点名\privkey.pem

有的版本可能叫server.pemserver.key,具体以宝塔面板 SSL 管理页面显示为准。只要把 win-acme 生成的证书文件复制到对应目录,然后让 Web 服务器重载配置,证书就更新生效了。

我写了一个 PowerShell 脚本deploy-to-bt.ps1,放在C:\win-acme\scripts\下:

$domain = "example.com" $sourceDir = "C:\win-acme\certs\$domain" $targetDir = "C:\www\ssl\$domain" Copy-Item "$sourceDir\cert.pem" "$targetDir\fullchain.pem" -Force Copy-Item "$sourceDir\key.pem" "$targetDir\privkey.pem" -Force # 重载 Nginx(根据服务器类型选择) & "C:\nginx\nginx.exe" -s reload # 如果用的是 Apache,可以执行: # & "C:\BtSoft\apache\bin\httpd.exe" -k restart

脚本逻辑很简单:把新证书复制到宝塔证书目录,然后重载 Web 服务。这里有个细节要注意——Nginx 重载前可以先执行nginx -t检查配置语法,防止证书文件格式异常导致 Nginx 启动失败。把nginx -t加在 reload 前面,失败时脚本直接退出:

& "C:\nginx\nginx.exe" -t if ($LASTEXITCODE -ne 0) { Write-Error "Nginx config test failed, abort reload." exit 1 } & "C:\nginx\nginx.exe" -s reload

5.3 让部署脚本随续期任务联动

win-acme 提供了一个参数,续期成功后可以执行外部脚本,这样计划任务只需要调用 win-acme 即可,部署联动的完整性由 win-acme 自己保障。参数写法是:

C:\win-acme\win-acme.exe --renew --certificate "example.com" --validation aliyun --store pemfiles --pemfiles-path "C:\win-acme\certs\example.com" --script "powershell.exe -ExecutionPolicy Bypass -File C:\win-acme\scripts\deploy-to-bt.ps1"

--script参数等价于旧版本里的--postscript,表示证书处理完成后执行对应命令。如果证书尚未到期、没有触发续期,脚本不会执行。这个“事件驱动”的联动方式避免了每天重复复制文件和重载服务,只有真正拿到新证书才触发部署,干净利落。

有一点需要注意:--script默认只在证书成功创建或成功续期后执行。首次创建证书时也会触发,所以你在配置计划任务之前手动跑一遍这条命令,就能立刻验证全链路是否通畅。

6. 与宝塔面板的细节磨合:证书路径、站点绑定与重载时机

6.1 宝塔面板 SSL 配置区域解析

打开宝塔 Windows 版面板,进入站点 → SSL 设置,会看到证书和私钥两个文本框。手动申请证书时你需要把cert.pem内容粘贴到证书栏,把key.pem内容粘贴到私钥栏。但自动化流程里没人去做复制粘贴的工作,所以脚本直接操作磁盘上的证书文件更符合实际。

宝塔面板在切换或重载证书的时候,会读取C:\www\ssl\站点名\下的文件。你只要保证这个目录里的文件内容是新的,然后触发 Nginx 重载即可。宝塔面板自身的“SSL 证书到期时间”显示有缓存,可能需要 5-10 分钟才会刷新,不影响实际证书生效。

还有个坑值得单独提:部分宝塔版本在 Nginx 配置里并不是直接用fullchain.pem文件,而是把证书内容以ssl_certificate指令直接写在站点配置文件中。这种情况下单纯替换文件不生效,脚本需要额外修改nginx.conf或宝塔生成的站点 conf 文件。判断方法很简单:打开站点配置文件,搜索ssl_certificate,如果后面跟的是绝对路径说明是文件引用模式,如果后面直接是data:或者一长串 Base64 内容,说明是内联模式。内联模式建议改成文件引用模式,后续自动化才能稳定工作。

6.2 在计划任务中串联“续期 + 部署”

如果不想用--script参数,也可以在计划任务里串联两条命令。我在“操作”选项卡中新建两个操作:

  1. 第一个操作执行win-acme.exe续期命令
  2. 第二个操作执行deploy-to-bt.ps1

但这里有个严重隐患:第二个操作无法判断第一个操作是否真的续期成功。如果证书没到期,win-acme 直接跳过续期,后续脚本依然会执行一次复制和重载。虽然复制的是同一个文件,重载 Nginx 不会带来什么损害,但每天凌晨 Nginx 重载一次确实没必要,更关键的是可能打断正在进行的连接。所以--script参数方案天然比“两个动作串联”更合理,这也是我踩过一次坑后的改法。

6.3 Apache 用户的特殊处理

Windows 宝塔使用 Apache 的站点相对少,但必须提一下。Apache 重载配置用的不是reload而是restart,而且 Windows 版 Apache 在证书文件被占用时可能提示无法读取。常见原因是站点正被其他进程读取,或者目录权限不足。给C:\www\ssl\目录给到运行 Apache 的用户读取权限即可。还有 Apache 对私钥文件的权限很敏感,如果私钥文件能被其他账户读取,Apache 可能拒绝启动。

7. 常见问题与排查技巧实录

7.1 问题速查表

现象可能原因解决办法
证书申请报“验证失败”DNS TXT 记录未生效;插件未正确调用 API检查 AccessKey 权限、确认域名解析在阿里云,等待 1-2 分钟重试
win-acme 提示 403 或 UnauthorizedRAM 子用户没授权;策略错误控制台确认已绑定AliyunDNSFullAccess
计划任务运行但证书不更新win-acme 认为剩余天数超过 30 天正常现象,剩余 30 天内才会续期。可用--renewal-days 60调整续期提前量
更新后浏览器仍显示旧证书Nginx 未重载;文件复制失败手动执行nginx -tnginx -s reload;检查脚本执行日志
宝塔面板显示证书未更新界面缓存关闭面板页面重新登录;或检查站点 conf 中的引用路径
通配符证书申请失败阿里云 RAM 权限不含_acme-challenge记录的控制权给 RAM 用户额外授权AliyunDNSFullAccess并刷新策略
脚本执行报错:路径不存在站点目录名不是域名在宝塔面板查看站点实际路径并修改$targetDir

7.2 高频翻车点:阿里云 DNS 解析验证的“生效延迟”

win-acme 调用阿里云 API 添加 TXT 记录后,会立刻请求 Let's Encrypt 验证。正常情况下阿里云解析是秒级生效,但偶尔会遇到新增记录需要几十秒才能被公共 DNS 查询到的情况。win-acme 对这个问题有内置重试机制,默认会在一定时间内反复查询。如果你遇到第一次验证失败,不要急着改配置,直接再运行一次申请命令。实测遇到验证失败后间隔 2 分钟重试,成功率接近 100%。

这里面还有个容易忽略的点:如果你之前手动为_acme-challenge配置过一条 TXT 记录,旧记录没删除会导致校验内容不一致。win-acme 插件在每次申请时先清理同名记录再新增,所以正常不会冲突。但如果你用其他工具手动加过记录,建议先删干净。

7.3 计划任务“运行了但啥也没发生”的排查方法

计划任务跑完看不到日志,这是新手最容易慌的场景。win-acme 默认会在执行目录(或C:\ProgramData\win-acme\log)生成日志文件。排查步骤如下:

  1. 打开任务计划程序,找到win-acme-renew任务
  2. 右键“运行”,看任务状态
  3. 打开C:\ProgramData\win-acme\log下最新的日志文件
  4. 搜索Certificates created或者No renewals needed字样

如果日志显示No renewals needed,说明证书还是充足状态,这是正常现象。想测试完整续期流程,可以把 win-acme 的续期阈值调大,比如--renewal-days 90,这样它就会立即执行一次续期。注意这不是作弊,只是把续期窗口拉满,让所有证书都进入“待续期”状态。

7.4 服务器重启后证书文件消失

有个特殊情况——如果宝塔的 SSL 目录被放在了内存盘或者临时目录(有些运维习惯把临时文件放到C:\Windows\Temp之类的地方),服务器一重启证书就没了。所以证书目录一定要落在普通数据盘或者系统盘持久目录,并且避开系统自动清理目录。win-acme 默认的证书存放目录C:\win-acme\certs\是持久安全的,把部署脚本的源文件指向这里没问题。

7.5 关闭或保留面板“自动续期”开关

如果你以前在宝塔里手动申请过证书,并且开启了面板自带的“自动续期”开关,建议先把它关掉,改用 win-acme 这套方案。两套自动化机制并存时,可能在半夜同时触发,虽然不至于把证书搞坏,但日志会变得混乱,排查问题时找不准是哪一条链路的锅。把职责收敛到一条自动化链路里,运维的复杂度会低很多。

8. 运维经验谈:再分享几个让这套方案更稳的细节

这套自动化方案跑了很长一段时间后,我总结出几个值得额外留意的细节,分享出来供参考。

第一点是关于阿里云 RAM 子用户的权限收敛。AliyunDNSFullAccess权限虽然只覆盖 DNS 服务,但如果 AccessKey 泄露,对方依然可以操纵你的所有域名解析记录,把流量劫持到任意 IP。更稳妥的组合是创建一个自定义策略,只允许操作指定 ZoneId 的 TXT 记录。阿里云 RAM 策略支持按资源维度授权,操作路径是:RAM 访问控制 → 权限策略 → 创建自定义策略 → 选择“脚本编辑”,然后针对acs:alidns:*:{账号ID}:domain/{你的域名}资源授权AddDomainRecordDeleteDomainRecordDescribeDomainRecords三个操作。这个配置能把泄露风险降到最低。

第二点关于监控告警。即使有自动续期,还是建议配置一个人工兜底——比如 certbot 或者 win-acme 日志里检测到连续失败就发邮件。最简单的做法是宝塔面板自带的计划任务加上“邮件通知”功能,每天跑完续期任务后发送一行结果。不引入额外监控系统也能实现基本的“故障感知”。阿里云云监控也支持自定义报警,可以监控定期请求证书接口的返回结果,不过这个方案需要额外写一个健康检查脚本,丰俭由人。

第三点关于证书类型的取舍。win-acme 默认申请的是单域名证书,也就是证书只覆盖你填写的那个域名。如果你的站点需要覆盖example.comwww.example.com,在申请时把两个域名都填入。需要更多的子域名时,直接申请通配符证书*.example.com。通配符证书的签发验证次数多一点,但自动化之后成本无所谓。唯一需要注意的是通配符证书在部分老客户端设备上兼容性差一些(比如某些旧 Android),如果目标用户群体有大量老旧设备,建议还是按具体域名逐个签单域名证书,成本在高频更新上并不大。

第四点是证书链的完整性。win-acme 的 PEM 文件目录下会生成多个文件,常见的包括cert.pemchain.pemfullchain.pemkey.pem。宝塔 Nginx 配置里必须用fullchain.pem而不是cert.pem,因为cert.pem只有站点证书,缺少中间证书链,很多浏览器会报告“证书链不完整”的错误。哪怕你用的是 Apache,也必须导入 fullchain。这一点是初用 win-acme 的人最容易踩的坑,我在第一次自动化部署时就因为弄混了这几个文件,导致 HTTPS 握手异常。

第五点是计划任务的执行身份。计划任务里我推荐勾选“不管用户是否登录都要运行”,并且用一个专门的系统账户来跑。很多人在配置计划任务时图省事,用当前登录的管理员账户,结果账户密码一改,计划任务就“无法启动”,续期也因此中断。更稳妥的做法是在计划任务属性里指定一个专用账户,比如SYSTEM账户,避免密码过期问题。但SYSTEM账户访问网络共享或者某些网络盘可能有权限限制,如果你要把证书输出到网络位置,就需要先测试权限。最省事的方案是全部落在本地磁盘,交给SYSTEM账户执行即可。

第六点也是最后想说的一点——虽然自动化已经很稳定了,但“人”的兜底机制依然要有。我的习惯是每一台服务器上放一个check-ssl.ps1脚本,一个月手动跑一次,输出所有域名的证书到期时间。虽然没有搞到一键巡检那么花哨,但这个简单的脚本能让我对全部站点证书状态心里有数。自动化要敢用,但也不能失去对系统状态的掌控感。

这套 win-acme + 阿里云 DNS + 宝塔的组合,对我来说已经成了 Windows 服务器上证书管理的默认方案。换过脚本、换过任务方式,折腾几轮之后发现,像这类基础设施自动化,最重要的反而不是某项技术多先进,而是链路足够简单可靠、每一步都有日志、失败时能快速定位到具体环节。希望这篇文章能帮你少走一些弯路,一次性把证书自动续期这件事彻底解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询