尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

win-acme 实战:Windows 服务器上为 nginx 自动申请与续期免费 SSL 证书

win-acme 实战:Windows 服务器上为 nginx 自动申请与续期免费 SSL 证书 简介win-acme.v2.2.9.1701.x64.pluggable.zip 是一款面向 Windows 平台的免费 SSL 证书自动获取与部署工具包适合网站管理员、系统集成商及需要为 IIS、nginx 等服务器快速配置 HTTPS 的用户尤其适合官网下载缓慢、希望本地化获取工具的场景。压缩包共 28 个文件体积 35.58MB核心可执行文件 wacs.exe 负责证书申请与续期21 个 PowerShell 脚本覆盖 Exchange、SQL、DNS、Kemp 等组件证书导入另有 bat 批处理、JSON 配置和 XML 模板辅助自动化部署文件结构清晰便于按需选用。目前已有 369 人学习下载。使用时可配合作者提供的中文教程快速上手理解证书申请、更新、定时任务设置等环节从而在低成本前提下为多个站点统一管理 Lets Encrypt 证书减少手工续期负担和因证书过期导致的访问异常。整体而言这套工具对预算有限但又重视传输安全的小型网站和项目具有很高的实用价值。1. win-acme 是什么Windows 上用免费 SSLnginx 不再当二等公民在 Windows Server 上跑 nginx 的兄弟基本都被证书折腾过Lets Encrypt 的免费 SSL 大家都想要但 certbot 在 Windows 下装起来问题一堆手动续期更是噩梦。win-acme 就是专职解决这个的工具v2.2.9.1701 的 x64 pluggable 打包版解压后右键以管理员运行交互式向导几步就能申请到证书并自动配置续期计划任务。它能用 HTTP、TLS-ALPN、DNS 三种方式做验证证书到手后按 nginx 需要的 PEM 格式输出再配合一段 reload 脚本达到“到期前自动续期、nginx 自动加载新证书”。适合谁Windows 上跑 nginx、不想手动更新证书、也不想为证书单独配一台 Linux 服务器的运维和独立开发者。下面我直接按“原理 → 安装 → 集成 → 避坑 → 验证”的顺序展开每一步都是能照着敲的。2. 选型与原理让 win-acme 替你跑通 ACME 协议先搞懂三种验证方式2.1 为什么不用 certbotWindows 生态下的 ALPN 与计划任务ACME 是 Lets Encrypt 的自动证书管理协议win-acme 是它的 Windows 客户端。很多人第一反应是装 certbot但 certbot 官方对 Windows 的支持一直不算完整依赖 Python 环境安装后要手动做成 Windows 服务续期逻辑还要自己写计划任务包一层。win-acme 原生就跑在 Windows 上解压即用自带“创建证书 → 续期 → 部署到目标程序”的完整链路还能自动往任务计划程序里写一条续期任务到期前 30 天自动重新申请。这一点对只想让 nginx 一直有证可用的场景特别省心。win-acme 的交互式向导会问你几个问题域名、验证方式、证书存储位置、要不要绑定 IIS、要不要注册计划任务。回答完了它自己去和 Lets Encrypt 的 ACME 服务器对话申请、下载、安装全程不需要你手动复制 challenge 文件。我一般习惯先用交互式模式把第一张证书跑通然后用命令行参数固化成一个可重复执行的命令方便以后批量加域名。这种方式在 Windows 上比 certbot 加 bat 脚本要稳定因为 win-acme 自带对 Windows 服务权限、IIS、计划任务的处理不会出现 Linux 工具迁移过来后路径分隔符和权限模型全部对不上的问题。在选型上还有一点要提win-acme 的每次续期不会重新生成私钥除非你用了相对较新的“证书轮换”配置。默认行为是私钥保持不变只替换证书文件。这对 nginx 加载很友好因为你不用担心 reload 时私钥和证书不匹配。在 nginx 里只要配置一次ssl_certificate和ssl_certificate_key后面续期后覆盖同名文件再 reload 一次就行。2.2 三种验证方式HTTP、TLS-ALPN、DNS 分别怎么选win-acme 的 v2.x 支持三种验证方式选错了会在一开始就翻车。我把它们放在一张表里对比后面再逐个说参数。验证方式需要打开的端口适用场景win-acme 中对应参数HTTP-0180有公网入站nginx 在 80 端口能响应--validation httpTLS-ALPN-01443只开了 443不想碰 80--validation tls-alpnDNS-01无入站端口泛域名、内网、CDN 后面--validation dnsHTTP-01 是最直观的Lets Encrypt 会访问http://你的域名/.well-known/acme-challenge/xxxwin-acme 需要在 80 端口上临时起一个 HTTP 响应或者借助 nginx 的 webroot 目录。如果你的 nginx 已经在 80 端口挂着业务那么就用--webroot指定一个 nginx 能访问到的静态目录win-acme 把验证文件写到那里nginx 直接按路径返回验证结束后自动删除。这个方式最简单只要防火墙放行 80 就行。TLS-ALPN-01 是在 443 端口上用 ALPN 协议扩展做验证win-acme 会临时起一个 HTTPS 服务Lets Encrypt 通过你域名的 443 端口来访问。这个方式的好处是你不用在 nginx 配置里为.well-known路径单独加 location坏处是它要求 443 端口当前没有被别的服务占用。如果你的 nginx 已经用了 443这个验证方式会冲突除非你让 win-acme 使用nc.exe或自带服务短暂绑定 443但 nginx 还占着端口所以实际使用中反而容易踩坑。DNS-01 是难度最高但最通用的方式它要求你在 DNS 服务商那边添加一条 TXT 记录证明你对域名有控制权。好处是服务器可以没有公网 IP、没有开放任何入站端口还能签泛域名。坏处是你得先在 win-acme 里配置 DNS 插件比如阿里云、Cloudflare、腾讯云的 API 密钥。v2.2.9.1701 这个 pluggable 包自带了常见 DNS 插件配置好之后 win-acme 会自动调 API 添加 TXT 记录验证完再删除。如果你用的是小众 DNS 服务商可能还要找额外的脚本。我个人建议能走 HTTP 就走 HTTP没必要一上来就折腾 DNS 插件。2.3 pluggable 版和 x64 版到底多了什么win-acme 的发布包有几种形态普通版、pluggable 版、x64 版、x86 版。标题里这个v2.2.9.1701.x64.pluggable.zip意思是同时具备两个属性x64 是 64 位原生程序pluggable 是带插件扩展的完整版。普通版本通常只包含核心 ACME 申请逻辑够你完成 HTTP 验证并生成证书。pluggable 版额外带了一堆插件常见的有DNS 插件用于 DNS-01 验证、IIS 部署插件、PEM 文件输出插件、脚本部署插件。nginx 用不到 IIS 插件但 PEM 输出插件几乎是必用的因为 win-acme 默认会把证书装进 Windows 证书库或者导出成 PFXnginx 并不吃 PFX。装了 PEM 插件后你可以在创建证书时选择“保存为 PEM 文件”它会把证书链和私钥分别写到指定目录文件名和后缀都正常省掉自己用 openssl 转格式的步骤。x64 版在 64 位 Windows 上不会触发文件系统重定向跑计划任务和访问 Certificate Store 都比 32 位版省心。如果你的系统是 Windows Server 2016 或更新的 64 位版本直接选 x64 没错。下载后得到的是一个 zip解压时要完整解压不要只把 wacs.exe 拖出来因为同目录下还有settings.json和插件 DLL缺一个后面就会报“插件加载失败”。3. 安装与首次申请从解压 zip 到拿到第一张证书3.1 解压后的目录结构与初始化先把 zip 解压到固定目录我习惯放在C:\win-acme不要放在带空格的路径里避免计划任务和脚本转义出问题。解压后你会看到wacs.exe、settings.json、store目录、plugins目录等。wacs.exe 就是主程序命令行和交互式都靠它。settings.json 保存全局配置比如默认联系人邮箱、代理服务器、自动更新开关。第一次运行前建议先用文本编辑器打开 settings.json 看一眼确认email为空也没关系向导会让你填。首次运行 wacs.exe 一定要右键“以管理员身份运行”因为后续写计划任务和访问证书库都需要管理员权限。进入交互界面后主菜单有大概这几项创建证书、续期所有证书、列出计划任务、更改设置。第一次选“创建证书”即可。它会让选择证书来源一般选Manual手动输入域名如果你在 IIS 里配置了站点可以选IIS让它自动抓绑定域名。nginx 用户选 Manual 就行把www.example.com和example.com都填进去一次性签一个 SAN 证书这样两个域名共用一张证。这里有个关键参数密钥类型。win-acme 默认走 RSA 2048如果你不想以后再换可以直接选 ECC P-256。ECC 证书在 nginx 里性能更好但有些老旧客户端不认。如果只是给自己或者内部系统用建议直接用 ECC如果对兼容性有执念就保留 RSA。我第一次踩坑就是选了 RSA后来换 ECC 重新签了一张nginx 配置没动只是私钥文件变大变小的问题影响不大。3.2 交互式申请的第一个完整流程跟着向导走大概流程是这样的第一步输入域名列表多个域名用逗号分隔。它会在屏幕上显示一个序号你直接输1,2,3这样的编号或者直接输域名都行。确认后它会做 DNS 解析检查如果域名还没解析到当前服务器 IP会提示但一般不会阻止申请。第二步选验证方式。这里我建议第一次先用 HTTP它会问你是使用本机临时服务还是指定 webroot。选“指定 webroot”然后填 nginx 的 html 目录比如C:\nginx\html。win-acme 会把验证文件写到C:\nginx\html\.well-known\acme-challenge\下nginx 只要配置了location /.well-known/acme-challenge/ { root C:/nginx/html; }就能被外网访问到。注意 nginx 里要把C:\nginx\html写成正斜杠C:/nginx/html否则会报路径找不到。第三步选证书存储方式。这里千万别选 Windows 证书库否则后面 nginx 用不了。选“PEM 文件”然后指定输出目录比如C:\win-acme\certs。win-acme 会问你是不是要同时导出私钥选“是”。它会生成两个文件一个是证书链一个是私钥文件名类似example.com-chain.pem和example.com-key.pem。第四步选部署方式。nginx 没有现成插件选“无”或者“运行脚本”都行。为了自动续期后能 reload nginx建议选“运行脚本”然后指定一个 bat 文件路径脚本内容就是运行nginx -s reload。这样每次续期成功win-acme 会自动执行这个脚本。第五步注册计划任务。向导会问是否创建续期任务选“是”并指定运行账户。建议选“SYSTEM 账户”这样不需要维护密码。间隔时间用默认的“每天检查一次”即可win-acme 自己会在到期前判断是否需要续期。整个流程走完它会显示申请结果并把证书路径打印出来。第一次能顺利看到这个界面后面就简单了。3.3 非交互式命令行申请把流程固化成脚本交互式点一次没问题但如果你要维护多台服务器或者以后想一键加域名还是要用命令行。win-acme 的命令行参数是大写开头的驼峰格式下面是我实际用的一个例子wacs.exe --source manual --host example.com,www.example.com --validation http --webroot C:\nginx\html --target pem --pem-path C:\win-acme\certs --script C:\win-acme\reload-nginx.bat --accepttos --email adminexample.com这个命令里--source manual表示手动指定域名--host后面接的是域名的逗号列表--validation http表示用 HTTP-01 验证--webroot指定 nginx 的静态根目录--target pem是调 PEM 插件输出证书文件--pem-path指定输出位置--script是续期成功后要执行的脚本--accepttos跳过交互式用户协议确认--email是 Lets Encrypt 账户邮箱。参数说明--webroot和--validation http必须配套如果你已经选择 tls-alpn 就不要带这个参数否则会报冲突。--target pem要求 pluggable 版本里带了 PEM 插件普通版可能没有。--script指定的脚本路径里的空格需要整体用双引号包住而且脚本自身必须能独立运行win-acme 不会替你把 nginx 重启它只是调用它。跑完命令后如果没报错就可以到C:\win-acme\certs下看产物。我建议把这条命令保存成一个renew-all.bat以后手动续期只需要双击运行避免再进交互式菜单。3.4 第一次申请后的文件产物检查拿到证书后先别急着配 nginx用文本编辑器打开证书文件看一眼。证书链文件开头应该是-----BEGIN CERTIFICATE-----私钥文件开头应该是-----BEGIN RSA PRIVATE KEY-----或者-----BEGIN EC PRIVATE KEY-----取决于你选的密钥类型。有的版本私钥文件名后缀可能是.key.txt不影响使用但最好直接改名成.key避免 nginx 里配置时后缀不熟悉造成困惑。还要检查证书链文件里是不是包含了两张证书第一张是你的域名证书第二张是中间证书。如果只有一张说明 win-acme 没把中间证书拼进去nginx 会报 incomplete chain导致浏览器不认。pluggable 版一般不会出这个问题但如果你用了非官方插件一定要确认。文件检查完顺手在命令行里用 certutil 看下有效期certutil -dump C:\win-acme\certs\example.com-chain.pem这个命令在 Windows 自带不用额外装 openssl。输出里会显示 NotBefore 和 NotAfter确认有效期是 90 天说明申请成功。从这一刻起你的 nginx 就可以挂上这张证书了。4. 与 nginx 集成证书路径、权限与自动续期4.1 把 PEM 证书和私钥放进 nginx 配置nginx 在 Windows 下加载证书时路径要用正斜杠并且配置文件里的路径要指向实际存在的文件。我把 win-acme 输出目录直接定为C:\win-acme\certs然后在 nginx 配置里写server { listen 443 ssl http2; server_name example.com www.example.com; ssl_certificate C:/win-acme/certs/example.com-chain.pem; ssl_certificate_key C:/win-acme/certs/example.com-key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这个配置里ssl_certificate指向的是证书链文件不是单独的域名证书。如果你只填了域名证书浏览器会报“缺少中间证书”。ssl_certificate_key指向私钥文件。win-acme 生成的文件名可能是example.com-chain.pem和example.com-key.pem以实际生成的文件名为准。nginx 在 Windows 上启动时会以当前服务账户读取这两个文件。如果你的 nginx 是用官方 Windows 包跑的默认以当前用户身份启动只要该用户对C:\win-acme\certs有读取权限即可。如果直接双击 nginx.exe 在前台运行用的是当前登录用户如果注册成 Windows 服务一般是 LocalSystem 或 NetworkService你需要确认这两个账户对目录有权限。最简单的做法是右键目录 → 属性 → 安全 → 编辑把Users组的读取权限加上但更规范的做法是只给运行 nginx 的那个账户授权。4.2 nginx 的 HTTP 验证路径配置如果你用 HTTP-01 验证nginx 上必须提前配置好.well-known路径的映射。在 80 端口 server 块里加这一段server { listen 80; server_name example.com www.example.com; location /.well-known/acme-challenge/ { root C:/nginx/html; default_type text/plain; } location / { return 301 https://$host$request_uri; } }这个配置的含义是验证请求打到 80 端口时直接去C:/nginx/html/.well-known/acme-challenge/目录找文件找不到就返回 404。win-acme 写文件时会自动创建这个目录验证成功后又自动删掉。要注意root指令后面不能把.well-known也写上否则 nginx 会找C:/nginx/html/.well-known/.well-known。我第一次就写成了root C:/nginx/html/.well-known结果验证一直 404后来才反应过来 root 和 alias 的区别。4.3 续期任务与 reload避免证书更新后 nginx 还用旧的win-acme 注册的计划任务默认是每天触发一次它内部判断证书剩余天数如果少于 30 天就重新申请。续期成功后win-acme 会根据你在创建向导里选择的“部署方式”执行动作。如果你选了“运行脚本”它会在新证书写入完成后运行你指定的 bat 脚本。我的 reload-nginx.bat 内容很简单echo off C:\nginx\nginx.exe -s reload -p C:\nginx这里-p指定 nginx 的安装目录避免默认路径不对导致 reload 失败。如果 nginx 注册成了 Windows 服务可以改用net stop nginx net start nginx但 reload 比重启更快也不会中断连接。脚本执行时win-acme 是以计划任务账户通常是 SYSTEM运行的如果 SYSTEM 对 nginx 目录没有权限reload 会失败但 win-acme 不会报错你只会发现证书文件更新了nginx 没生效。所以脚本里最好加一句输出和退出码校验C:\nginx\nginx.exe -s reload -p C:\nginx echo %ERRORLEVEL%如果输出不是 0就从任务计划程序的手动运行里看完整日志。血泪经验我一开始用了taskkill /f /im nginx.exe再重新启动导致所有连接瞬间断开后来才改成-s reload平滑切换。4.4 文件权限与自动更新时的常见连锁问题win-acme 更新证书文件时默认会先写临时文件再替换原文件这意味着文件的 ACL 可能会被重置。如果你之前手工给 nginx 账户授过权替换后权限还可能继承自C:\win-acme\certs目录所以要确保目录权限设置正确而不是单独给文件授权。如果你把证书输出到了 nginx 的 html 目录那就更危险证书私钥会被 web 服务器直接泄露任何人只要知道路径就能下载。千万不要那样做证书目录要和 web 根目录彻底分开。另外win-acme 在续期时会重写整个链文件如果 nginx 正在运行并持有旧文件句柄reload 后会自动打开新句柄。但如果计划任务执行过快、nginx reload 脚本还没跑完win-acme 就开始处理下一次续期有可能出现短时间证书文件不完整。这种情况非常少见但我在一台性能很差的虚拟机上遇到过后来在计划任务设置里加了“启动延迟 5 分钟”就再没出过问题。5. 避坑指南win-acme 在 Windows nginx 下最常见的五个问题5.1 申请时报错 “403 Forbidden”验证文件无法访问现象使用 HTTP-01 验证时win-acme 提示验证失败被 Lets Encrypt 拒绝错误通常包含Invalid response from http://.../.well-known/acme-challenge/...。原因验证路径返回的不是 win-acme 写入的文本内容而是 nginx 的 404、301 或反向代理内容。解决先用浏览器访问http://yourdomain/.well-known/acme-challenge/test.txt如果返回值不是预期检查 nginx 里是否配置了根目录正确以及 80 端口上的 server 块是否被重定向规则覆盖。win-acme 写文件后通常等几秒才发起验证所以不要在验证过程中去删文件。5.2 使用 TLS-ALPN-01 验证时win-acme 提示端口被占用现象选择了--validation tls-alpn但提示bind failed或port 443 in use。原因nginx 已经占用了 443 端口win-acme 临时服务无法绑定。解决如果你不想在验证期间停 nginx就不要用 TLS-ALPN改用 HTTP-01 配合 webroot。如果非要用 TLS-ALPN可以临时停止 nginx、执行申请、再启动 nginx但这样会让业务短时间中断并不划算。我后来固定用 HTTP-01把 nginx 的验证路径配置好之后再也没关心过端口占用。5.3 续期计划任务运行了但 nginx 还在用旧证书现象查看证书文件发现北京时间晚上已经更新过但用浏览器访问网站看到的证书有效期还是旧的。原因win-acme 续期后没有执行 reload 脚本或者脚本执行失败。解决打开任务计划程序找到 win-acme 的续期任务右键“运行”一次看返回码再手动执行一次 reload-nginx.bat确认nginx -s reload没有报错。如果脚本里没有加判断win-acme 会默认执行成功所以脚本里一定要写上echo %ERRORLEVEL%并检查。从那以后我每次续期后都会抽查一次证书有效期。5.4 nginx 启动时报 “cannot load certificate” 或 “PEM_read_bio_PrivateKey”现象修改 nginx 配置后启动报cannot load certificate或私钥解析失败。原因ssl_certificate指向了example.com-ca-only.pem只含中间证书或者私钥文件是 PFX 编码也有可能是文件路径用了C:\反斜杠导致 nginx 转义。解决确认ssl_certificate指向的是 win-acme 生成的-chain.pemssl_certificate_key指向的是-key.pem用正斜杠重写路径用文本编辑器确认 begin 和 end 行没有多余空格。如果私钥文件头是-----BEGIN PRIVATE KEY-----但有加密密码那就是申请时设置了密码需要重新生成不带密码的私钥。5.5 DNS-01 验证在阿里云/Cloudflare 上总是超时现象选择 DNS-01 验证win-acme 提示已写入 TXT 记录但 Lets Encrypt 等待 30 秒后就报DNS problem: NXDOMAIN。原因DNS 服务商 API 写入的 TXT 记录没有立刻生效或者_acme-challenge前缀解析到了 CDN 节点没有实时刷新。解决在 win-acme 的 settings.json 里调大DnsSleepSeconds默认是 30我一般改成 120。同时确认你填的域名是主域名不要连www也单独做 TXT 记录。如果插件不支持某些子域名需要把通配符域名*.example.com和裸域一起签这时候 DNS-01 几乎是唯一选择。6. 验证与进阶用 openssl 和计划任务确认证书真的续上了6.1 用 openssl 验证证书链和到期时间Windows 上如果没有 openssl可以用 PowerShell 的Get-PfxCertificate或者直接用下面这条命令检查远程站点openssl s_client -connect example.com:443 -servername example.com 2/dev/null | openssl x509 -noout -issuer -subject -dates这条命令会输出当前 nginx 实际返回的证书签发者、主题和有效期。你拿到的Not After应该和 win-acme 生成的文件一致。如果这里显示的到期日离现在只有 30 天左右说明续期还没成功不要等到最后一天才处理。我一般每周看一次连续三次都没问题基本就可以放心了。6.2 查看计划任务上一次运行结果打开任务计划程序找到名称类似win-acme renew (user)的任务切到“上次运行时间”和“上次结果”。如果结果是0x0说明正常如果是0x2或0x40010004之类的说明脚本或权限还有问题。双击任务在“操作”标签里可以看到它实际执行的命令一般是wacs.exe --renew --quiet。如果你想手动补一次续期直接在你的 win-acme 目录下运行wacs.exe --renew --quiet--quiet让它不弹交互界面全程写日志。日志默认在同目录下的.log文件里可以用记事本打开看最后几行通常会写Certificates updated或up to date。6.3 进阶多域名、泛域名和自动部署如果你有多个域名可以把它们都放在同一个 SAN 证书里命令行--host参数后继续用逗号分隔。但要注意 Lets Encrypt 对单张证书的域名数量有限制一般建议不超过 100 个。如果域名内有内网机器没法从公网验证就用 DNS-01 配合泛域名一次签*.example.com这样以后加子域名不需要重新申请证书只需要在 nginx 配置里指向同一套证书文件。对于自动部署你可以在 reload-nginx.bat 里加上业务系统重启步骤。比如我们这边是 nginx 反代一个 Java 服务证书更新后 nginx 要 reloadJava 服务不需要动。如果你的业务系统支持热更新证书也可以在脚本里curl一下本地管理接口触发它重新加载。注意脚本必须是“幂等”的重复执行不会出错因为 win-acme 可能在一天里重试多次。我自己现在每台 Windows 服务器都是同一套套路解压 win-acme 到固定目录先交互式签第一张证书把命令行参数复制到 bat计划任务注册好reload 脚本加上echo %ERRORLEVEL%然后在日历上每周提醒自己看一眼 openssl 的输出。这样坚持了小半年没再出现证书过期导致网站打不开的情况。希望这套流程和这些踩坑记录能帮你少走几趟弯路把免费 SSL 在 Windows nginx 上真正变成一件“不用管”的事。本文还有配套的精品资源点击获取
返回列表