Windows Server 配置 Let's Encrypt 免费 HTTPS 证书(WACS + Nginx 自动化方案)
一、方案说明与核心流程
1.1 适用场景
本方案专为部署了 Nginx 的 Windows Server 服务器设计,解决 Let's Encrypt 免费 HTTPS 证书的申请、格式转换、自动续期及 Nginx 适配问题,无需依赖 IIS,轻量化实现 HTTPS 全流程管理。
1.2 核心工具
- WACS(Win-ACME):Windows 下申请、自动续期 Let's Encrypt 证书的核心工具,支持脚本钩子实现证书自动导出;
- OpenSSL 1.1.1 Light:解决 WACS 生成的 PFX 证书与 Nginx 兼容问题,实现 PFX → crt/key 格式转换;
- PowerShell 脚本:自定义证书导出逻辑,自动完成格式转换并输出到指定目录;
- Nginx:配置 HTTPS 访问与 HTTP 强制跳转,适配静态文件和后端 API 服务。
1.3 核心步骤
- 下载并准备 WACS + OpenSSL 工具;
- 编写 PowerShell 脚本实现证书格式自动转换;
- 通过 WACS 申请证书并关联脚本,生成 Nginx 兼容的 crt/key 文件;
- 配置 Nginx 实现 HTTPS 访问与 HTTP 强制跳转;
- 验证证书续期功能,补充 Nginx 重载逻辑实现续期自动生效;
- 排查常见问题,保障全流程稳定运行。
二、核心工具准备:下载 WACS + 低版本 OpenSSL
2.1 下载 WACS(Win-ACME)
工具简介
WACS(Win-ACME)是 Windows 系统下免费申请、自动续期 Let's Encrypt 证书的工具,支持多种验证方式和脚本钩子,完美适配 Nginx 等服务器。
下载地址与安装
- 官方下载页:https://github.com/win-acme/win-acme/releases
- 推荐版本:选择最新稳定版,下载
win-acme.v2.x.x.x64.pluggable.zip(64位可扩展版); - 安装步骤:解压到任意目录(如
C:\win-acme),无需复杂安装,直接运行wacs.exe即可启动。
2.2 下载低版本 OpenSSL
下载作用
新版 OpenSSL 3.x 已禁用 RC2-40-CBC 算法,而 WACS 生成的 PFX 证书恰好使用该算法,高版本会导致证书提取失败;需下载 OpenSSL 1.1.1 Light 版,其原生支持 RC2 算法,可解决该兼容性问题。
下载地址与安装
- 下载版本:OpenSSL 1.1.1 Light 版;
- 直接下载链接:https://slproweb.com/download/Win64OpenSSL_Light-1_1_1w.exe;
- 安装注意:默认安装路径(如
C:\Program Files\OpenSSL-Win64)或自行记录,后续编写脚本时需匹配该实际安装路径。
三、编写证书导出脚本(适配 Nginx)
3.1 脚本核心作用
WACS 生成的证书默认格式为 PFX,无法直接被 Nginx 识别,需通过脚本自动从 PFX 文件中提取 Nginx 支持的 .crt(证书文件)和 .key(私钥文件),实现证书格式的自动转换。
3.2 最终脚本代码(中文乱码的话删除一下注释)
我的脚本文件是命名为"update_crt.ps1"
powershell
# WACS Renewal Hook - Export Nginx Cert (Compatible with OpenSSL 1.1.1 Light)
param(
[Parameter(Mandatory=$true)]
[string]$CertPfxPath,
[Parameter(Mandatory=$true)]
[string]$CertPassword
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
# Core Configuration
$domainName = "yourdomain.com" # 替换为你的实际域名
$baseDir = "$env:USERPROFILE\Desktop\yourdomain_crt" # 证书输出目录
$opensslPath = "C:\Program Files\OpenSSL-Win64\bin\openssl.exe" # 替换为你的OpenSSL实际安装路径
$sslCertFile = "$baseDir\$domainName.crt"
$sslKeyFile = "$baseDir\$domainName.key"
# Pre-Checks: Create directory if not exists
if (-not (Test-Path $baseDir)) {
New-Item -ItemType Directory -Path $baseDir | Out-Null
Write-Host "Created output directory: $baseDir"
}
if (-not (Test-Path $CertPfxPath)) {
throw "WACS PFX file not found: $CertPfxPath"
}
Write-Host "Using WACS new cert PFX: $CertPfxPath"
if (-not (Test-Path $opensslPath)) {
throw "OpenSSL not found at: $opensslPath"
}
Write-Host "Found OpenSSL at: $opensslPath"
# Extract Nginx Certificate (.crt)
Write-Host "Extracting Nginx certificate (.crt)..."
& $opensslPath pkcs12 -in "$CertPfxPath" -clcerts -nokeys -out "$sslCertFile" -nodes -password pass:$CertPassword -nomacver
if (-not (Test-Path $sslCertFile) -or (Get-Content $sslCertFile | Measure-Object -Line).Lines -lt 5) {
throw "Failed to extract valid .crt file from PFX"
}
Write-Host "Nginx cert saved to: $sslCertFile"
# Extract Nginx Private Key (.key)
Write-Host "Extracting Nginx private key (.key)..."
& $opensslPath pkcs12 -in "$CertPfxPath" -nocerts -out "$sslKeyFile" -nodes -password pass:$CertPassword -nomacver
if (-not (Test-Path $sslKeyFile) -or (Get-Content $sslKeyFile | Measure-Object -Line).Lines -lt 5) {
throw "Failed to extract valid .key file from PFX"
}
Write-Host "Nginx private key saved to: $sslKeyFile"
# Log Success
$logPath = "$baseDir\cert_export_log.txt"
$logContent = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Success! Nginx cert exported:
- Cert: $sslCertFile
- Key: $sslKeyFile
- Source PFX: $CertPfxPath
--------------------------------------------------`r`n"
Add-Content -Path $logPath -Value $logContent -Encoding ASCII
Write-Host "`n=== All Done! Nginx cert/key exported to $baseDir ==="
}
catch {
# Log Error
$errorLogPath = "$baseDir\cert_export_error.log"
$errorContent = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error: $($_.Exception.Message)
- PFX Path: $CertPfxPath
- OpenSSL Command: $opensslPath pkcs12 -in ""$CertPfxPath"" -nocerts -out ""$sslKeyFile"" -nodes -password pass:$CertPassword -nomacver
--------------------------------------------------`r`n"
Add-Content -Path $errorLogPath -Value $errorContent -Encoding ASCII
Write-Host "`n=== Error! Check log at $errorLogPath ===" -ForegroundColor Red
Write-Host "Error Details: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
3.3 脚本关键配置说明
- 替换
$domainName为你的实际域名(如yourdomain.com); - 替换
$opensslPath为你的 OpenSSL 实际安装路径(关键,避免报"OpenSSL not found"错误); $baseDir为证书输出目录,可根据需求修改,建议保持路径简洁方便查找。
四、使用 WACS 生成证书并关联自定义脚本
4.1 启动 WACS 并进入证书创建流程
以管理员身份运行 WACS 工具后,终端会输出以下初始菜单,我们首先选择证书创建的默认配置项:
bash
A simple Windows ACMEv2 client (WACS)
Software version 2.2.9.1701 (release, pluggable, standalone, 64-bit)
Connecting to https://acme-v02.api.letsencrypt.org/...
Connection OK!
Scheduled task looks healthy
Please report issues at https://github.com/win-acme/win-acme
N: Create certificate (default settings)
M: Create certificate (full options)
R: Run renewals (0 currently due)
A: Manage renewals (1 total)
O: More options...
Q: Quit
Please choose from the menu:
输入 N 并回车,进入「简易模式」的证书创建流程,终端会继续输出域名来源选择提示(因未部署 IIS,需选择手动输入域名):
bash
Running in mode: Interactive, Simple
Source plugin IIS not available: No supported version of IIS detected.
Please specify how the list of domain names that will be included in the
certificate should be determined. If you choose for one of the "all bindings"
options, the list will automatically be updated for future renewals to
reflect the bindings at that time.
1: Read bindings from IIS
2: Manual input
3: CSR created by another program
C: Abort
How shall we determine the domain(s) to include in the certificate?:
输入 2 并回车,终端会提示手动输入域名(需填写不带 http:// 或 https:// 的纯域名):
bash
How shall we determine the domain(s) to include in the certificate?: 2
Description: A host name to get a certificate for. This may be a
comma-separated list.
Host:
输入需要申请证书的纯域名(如 yourdomain.com,多个域名可用逗号分隔)并回车,终端会确认域名来源:
bash
Source generated using plugin Manual: yourdomain.com
4.2 关联自定义脚本(核心步骤)
域名确认后,终端会进入安装步骤选择环节(因项目未使用 IIS 部署,需选择「启动外部脚本/程序」来关联证书导出脚本):
bash
Installation plugin IIS not available: No supported version of IIS detected.
With the certificate saved to the store(s) of your choice, you may choose one
or more steps to update your applications, e.g. to configure the new
thumbprint, or to update bindings.
1: Create or update bindings in IIS
2: Start external script or program
3: No (additional) installation steps
Which installation step should run first?:
此处直接输入 2 并回车,开始配置自定义脚本:
选择后终端会提示输入「脚本执行文件路径」,注意此处需填写 PowerShell 的完整路径,而非我们编写的 .ps1 脚本路径:
bash
Description: Path to script file to run after retrieving the
certificate. This may be any executable file or a
Powershell (.ps1) script.
File:
填写 PowerShell 的默认路径并回车(不同系统路径一致,可直接复用):
bash
File: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
接下来终端会展示 WACS 内置变量说明,并提示输入脚本参数,这些参数用于将新生成的 PFX 证书路径、密码传递到我们的导出脚本中:
bash
{CertCommonName}: Common name (primary domain name)
{CachePassword}: .pfx password
{CacheFile}: .pfx full path
{CertFriendlyName}: Certificate friendly name
{CertThumbprint}: Certificate thumbprint
{StoreType}: Type of store (e.g. CentralSsl, CertificateStore,
PemFiles, ...)
{StorePath}: Path to the store
{RenewalId}: Renewal identifier
{OldCertCommonName}: Common name (primary domain name) of the previously
issued certificate
{OldCertFriendlyName}: Friendly name of the previously issued certificate
{OldCertThumbprint}: Thumbprint of the previously issued certificate
{vault://json/mysecret}: Secret from the vault
Description: Parameters for the script to run after retrieving the
certificate. Refer to
https://win-acme.com/reference/plugins/installation/script
for further instructions.
Parameters:
其中 {CacheFile} 和 {CachePassword} 是 WACS 官方内置变量,专门用于传递新证书的 PFX 文件路径和密码,需填写以下参数(替换为步骤3.2中编写的脚本的实际路径):
bash
Parameters: -ExecutionPolicy Bypass -File "C:\Users\Administrator\Desktop\yourdomain_crt\update_crt.ps1" -CertPfxPath "{CacheFile}" -CertPassword "{CachePassword}"
参数填写完成后,终端会再次展示安装步骤选择菜单,因仅需关联证书导出脚本,选择 3(无额外安装步骤)即可:
bash
1: Create or update bindings in IIS
2: Start external script or program
3: No (additional) installation steps
Add another installation step?: 3
4.3 证书申请与创建结果
选择完成后 WACS 会自动发起证书申请流程,过程中可能出现「80端口被占用」的报错,原因是 Let's Encrypt 验证域名所有权时需要临时占用 80 端口,需先关闭占用 80 端口的应用(如 Nginx、IIS 等),再重新执行证书申请流程。
若申请流程无异常,终端会输出以下内容,代表证书已成功申请并创建:
bash
Plugin Manual generated source yourdomain.com with 1 identifiers
Plugin Single created 1 order
Cached order has status invalid, discarding
[yourdomain.com] Authorizing...
[yourdomain.com] Authorizing using http-01 validation (SelfHosting)
[yourdomain.com] Authorization result: valid
Downloading certificate [Manual] yourdomain.com
Store with CertificateStore...
Installing certificate in the certificate store
Adding certificate [Manual] yourdomain.com @ 2026/2/4 in store My
Adding certificate CN=R12, O=Let's Encrypt, C=US in store CA
Adding Task Scheduler entry with the following settings
- Name win-acme renew (acme-v02.api.letsencrypt.org)
- Path C:\Users\Administrator\Desktop\win-acme.v2.2.9.1701.x64.pluggable
- Command wacs.exe --renew --baseuri "https://acme-v02.api.letsencrypt.org/"
- Start at 09:00:00
- Random delay 04:00:00
- Time limit 02:00:00
Adding renewal for [Manual] yourdomain.com
Next renewal due after 2026/3/31
Certificate [Manual] yourdomain.com created
N: Create certificate (default settings)
M: Create certificate (full options)
R: Run renewals (0 currently due)
A: Manage renewals (1 total)
O: More options...
Q: Quit
证书申请成功后,WACS 会自动调用我们编写的脚本,从 PFX 证书中提取出 Nginx HTTPS 配置所需的两个核心文件:yourdomain.com.crt(证书文件)和 yourdomain.com.key(私钥文件),并保存到脚本指定的输出目录中。
五、Nginx 配置 HTTPS
5.1 核心配置代码
nginx
worker_processes auto;
events {
worker_connections 4096;
multi_accept on;
accept_mutex off; # Windows环境无需互斥锁
}
http {
include mime.types;
default_type application/octet-stream;
# ========== 1. 80端口:强制跳转HTTPS ==========
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
# 所有HTTP请求强制跳转至HTTPS
return 301 https://$host$request_uri;
}
# ========== 2. 443端口:HTTPS核心配置 ==========
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name yourdomain.com www.yourdomain.com; # 匹配证书域名
# 核心:配置Let's Encrypt证书路径
ssl_certificate "C:/Users/Administrator/Desktop/yourdomain_crt/yourdomain.com.crt"; # 证书文件路径
ssl_certificate_key "C:/Users/Administrator/Desktop/yourdomain_crt/yourdomain.com.key"; # 私钥文件路径
# SSL安全基础配置(保障HTTPS安全性)
ssl_session_cache shared:SSL:10m; # SSL会话缓存
ssl_session_timeout 10m; # 会话超时时间
ssl_protocols TLSv1.2 TLSv1.3; # 仅启用安全的TLS版本
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; # 强加密套件
ssl_prefer_server_ciphers on; # 优先使用服务器端加密套件
# 静态文件服务(基础前端页面)
location / {
root C:/WorkFile/Website; # 替换为你的静态文件目录
index index.html index.htm;
}
# 后端API反向代理(基础接口转发)
location /api/ {
proxy_pass http://127.0.0.1:9573; # 后端API服务端口
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # 传递HTTPS协议标识
}
}
}
5.2 关键配置说明
- 证书路径替换 :将
ssl_certificate和ssl_certificate_key后的路径替换为前文脚本生成的yourdomain.com.crt和yourdomain.com.key实际存储路径; - 域名匹配 :
server_name需与申请证书的域名完全一致(包含www前缀需同步配置); - 80端口跳转:强制将所有 HTTP 请求重定向到 HTTPS,避免用户访问非加密链接,保障访问安全性;
- SSL 安全配置:仅启用 TLSv1.2/TLSv1.3 安全协议,搭配强加密套件,符合现代 HTTPS 安全规范;
- 业务适配 :
- 静态文件服务:
root后替换为你的前端静态文件实际存储目录; - 后端 API 代理:
proxy_pass后替换为你的后端 API 服务实际端口(示例为 9573)。
- 静态文件服务:
5.3 配置生效步骤
- 保存配置文件后,打开 CMD 进入 Nginx 安装目录;
- 执行
nginx -t验证配置语法,输出test is successful表示配置无错误; - 执行
nginx -s reload热重载配置(无需重启 Nginx),HTTPS 配置立即生效。
六、证书续期验证(WACS 终端操作)
6.1 WACS 菜单选项含义(续期相关)
在 WACS 主终端界面,核心续期相关选项及作用如下:
bash
A simple Windows ACMEv2 client (WACS)
Software version 2.2.9.1701 (release, pluggable, standalone, 64-bit)
Connecting to https://acme-v02.api.letsencrypt.org/...
Connection OK!
Scheduled task looks healthy # 关键:此提示代表自动续期定时任务正常
Please report issues at https://github.com/win-acme/win-acme
N: Create certificate (default settings) # 创建证书(默认配置)
M: Create certificate (full options) # 创建证书(完整选项)
R: Run renewals (0 currently due) # 运行续期(仅处理已到续期时间的证书)
A: Manage renewals (1 total) # 管理已创建的证书续期任务
O: More options... # 更多选项
Q: Quit # 退出
- 核心判断依据 :主界面的
Scheduled task looks healthy提示,直接说明 WACS 自动续期的定时任务已正常创建且无异常,证书到期会自动续期; - A(Manage renewals):进入续期管理菜单,可手动操作已创建的证书续期任务(如强制续期、查看详情)。
6.2 手动验证证书续期(测试有效性)
步骤1:进入续期管理菜单
在 WACS 主菜单输入 A 并回车,进入续期管理界面:
bash
Please choose from the menu:A
Welcome to the renewal manager. Actions selected in the menu below will be
applied to the following list of renewals. You may filter the list to target
your action at a more specific set of renewals, or sort it to make it easier
to find what you're looking for.
1: [Manual] yourdomain.com - 11 renewals, due 2026/4/1 # 证书信息:域名/续期次数/下次续期时间
E: Edit renewal # 编辑续期任务配置
D: Show details for the renewal # 查看续期任务详情
L: Show command line for the renewal # 查看续期任务的命令行参数
R: Run the renewal # 运行续期(非强制,仅到期才续)
S: Run the renewal (force) # 强制运行续期(忽略到期时间)
T: Run the renewal (force, no cache) # 强制续期且不使用缓存
U: Analyze duplicates for the renewal # 分析重复的续期任务
C: Cancel the renewal # 取消续期任务
V: Revoke certificate(s) for the renewal # 吊销证书
Q: Back # 返回主菜单
步骤2:执行强制续期测试
输入 S 并回车,触发强制续期(模拟自动续期流程),终端输出以下内容代表续期成功:
bash
Choose an action or type numbers to select renewals:S
Plugin Manual generated source yourdomain.com with 2 identifiers
Plugin Single created 1 order
Force renewing [Manual] yourdomain.com
Using cache for [Manual] yourdomain.com. To get a new certificate within 1 days, run with --nocache.
Store with CertificateStore...
Installing certificate in the certificate store
Replacing certificate [Manual] yourdomain.com @ 2026/2/5 in store My
Add Read rights for BUILTIN\Administrators
Installing with Script...
Script C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe starting with parameters -ExecutionPolicy Bypass -File "C:\Users\Administrator\Desktop\yourdomain_crt\update_crt.ps1" -CertPfxPath "C:\ProgramData\win-acme\acme-v02.api.letsencrypt.org\Certificates\oaqZm9UCikWy2VAk6bepJg-main-c94fd6b5b05937da6050fbdbea68e7724de44e6c-temp.pfx" -CertPassword "********"
Script finished # 关键:脚本执行完成,新证书已导出
Next renewal due after 2026/4/1 # 新的续期时间(续期成功)
Renewal for [Manual] yourdomain.com succeeded # 续期成功核心提示
Welcome to the renewal manager. Actions selected in the menu below will be
applied to the following list of renewals. You may filter the list to target
your action at a more specific set of renewals, or sort it to make it easier
to find what you're looking for.
1: [Manual] yourdomain.com - 12 renewals, due 2026/4/1 # 续期次数+1,验证生效
E: Edit renewal
D: Show details for the renewal
L: Show command line for the renewal
R: Run the renewal
S: Run the renewal (force)
T: Run the renewal (force, no cache)
U: Analyze duplicates for the renewal
C: Cancel the renewal
V: Revoke certificate(s) for the renewal
Q: Back
Choose an action or type numbers to select renewals:
6.3 重要提醒(必看)
⚠️ 核心注意事项:当前编写的
update_crt.ps1脚本仅实现了证书格式转换(PFX → crt/key),未包含重启 Nginx 的逻辑!
-
原因:首次申请证书时,Nginx 尚未配置 HTTPS,无法重启;
-
影响:证书续期后,新的 crt/key 文件已生成,但 Nginx 仍加载旧证书,HTTPS 不会立即生效;
-
解决方法:需手动修改
update_crt.ps1脚本,在证书导出成功后添加重启 Nginx 的命令,示例如下:powershell# 在脚本最后一行(Write-Host "=== All Done!..." 之后)添加: # 停止Nginx & "C:\nginx-1.24.0\nginx.exe" -s stop # 启动Nginx & "C:\nginx-1.24.0\nginx.exe" # 或热重载(推荐,不中断服务) # & "C:\nginx-1.24.0\nginx.exe" -s reload # 注意:替换为你的Nginx实际安装路径! -
验证:修改脚本后,再次执行强制续期,Nginx 会自动加载新证书,无需手动操作。
七、常见错误排查
7.1 证书申请失败:80端口被占用
现象
WACS 终端提示 http-01 challenge failed 或 port 80 is in use,证书申请流程中断。
原因
Let's Encrypt 的 http-01 域名验证机制需要临时占用 80 端口,Nginx、IIS、IIS Express 等服务会抢占该端口。
解决方法
- 打开 CMD,执行
netstat -ano | findstr :80查看占用 80 端口的进程 PID; - 停止占用进程:
- Nginx 占用:执行
nginx -s stop; - IIS 占用:打开「服务」停止
World Wide Web Publishing Service; - 其他进程:通过任务管理器结束对应 PID 的进程;
- Nginx 占用:执行
- 重新执行 WACS 证书申请流程,验证通过后再重启被停止的服务。
7.2 脚本执行失败:OpenSSL 路径错误
现象
WACS 续期/申请时提示 OpenSSL not found at: XXXXX,脚本执行失败,无 crt/key 文件生成。
原因
PowerShell 脚本中 $opensslPath 变量配置的路径与 OpenSSL 实际安装路径不匹配。
解决方法
-
找到 OpenSSL 安装目录(默认路径为
C:\OpenSSL-win64\bin\openssl.exe); -
修改
update_crt.ps1脚本中的$opensslPath变量,示例:powershell$opensslPath = "C:\OpenSSL-win64\bin\openssl.exe" # 替换为实际路径 -
保存脚本后,在 WACS 中执行「强制续期」测试脚本是否正常运行。
7.3 Nginx 启动失败:证书路径错误/权限不足
现象
执行 nginx -t 提示 SSL_CTX_use_certificate_chain_file("XXX.crt") failed 或 no such file or directory。
原因
- 证书路径配置错误(Windows 路径需用
/或\\,不能用单个\); - Nginx 进程无权限访问证书存储目录(如管理员桌面专属目录)。
解决方法
-
修正证书路径格式,示例:
nginx# 正确示例(推荐使用/) ssl_certificate "C:/Users/Administrator/Desktop/yourdomain_crt/yourdomain.com.crt"; # 或双反斜杠格式 ssl_certificate "C:\\Users\\Administrator\\Desktop\\yourdomain_crt\\yourdomain.com.crt"; -
权限问题处理:将证书文件移动到非管理员专属目录(如
C:\nginx\cert),并同步修改 Nginx 配置中的证书路径; -
重新执行
nginx -t验证配置,无报错后执行nginx -s reload生效。
7.4 浏览器提示「证书不安全/无效」
现象
访问 https://yourdomain.com 时,浏览器地址栏显示红色叉号,提示「证书不被信任」「域名不匹配」或「证书已过期」。
原因
server_name与证书域名不一致(如证书包含www.yourdomain.com,Nginx 仅配置yourdomain.com);- SSL 协议配置过低(启用了 TLSv1.0/TLSv1.1 等不安全协议);
- 证书未成功续期,已过有效期。
解决方法
-
保证域名匹配:Nginx 的
server_name需包含证书覆盖的所有域名,示例:nginxserver_name yourdomain.com www.yourdomain.com; -
精简 SSL 协议:仅保留安全的 TLSv1.2/TLSv1.3,移除低版本协议,示例:
nginxssl_protocols TLSv1.2 TLSv1.3; -
证书过期处理:打开 WACS 终端执行「强制续期」,生成新证书后重载 Nginx 配置。
7.5 证书续期成功但 Nginx 未加载新证书
现象
WACS 终端显示 Renewal for [Manual] yourdomain.com succeeded,证书文件已更新,但浏览器仍提示证书即将过期。
原因
update_crt.ps1 脚本未添加 Nginx 重启/热重载逻辑,Nginx 进程仍加载旧的证书文件。
解决方法
参考第六章 6.3 节,在 update_crt.ps1 脚本末尾添加 Nginx 热重载命令(推荐,不中断服务),示例:
powershell
# 替换为你的Nginx实际安装路径
& "C:\nginx-1.24.0\nginx.exe" -s reload
添加后保存脚本,重新执行强制续期,Nginx 会自动加载新证书。
八、全流程验证与总结
8.1 全流程验证
- 证书验证:进入证书目录,确认
yourdomain.com.crt和yourdomain.com.key文件存在且为最新生成; - Nginx验证:执行
nginx -t提示配置正常,nginx -s reload无报错; - 访问验证:浏览器输入
http://yourdomain.com自动跳转https,地址栏显示小锁图标,API接口https://yourdomain.com/api可正常访问; - 续期验证:WACS终端执行强制续期(A→S),提示
Renewal succeeded即为续期流程正常。
8.2 总结
本文针对 Windows Server + Nginx 环境,通过 WACS 实现 Let's Encrypt 免费 HTTPS 证书的申请与自动续期,配合自定义 PowerShell 脚本完成证书格式转换,最终通过 Nginx 极简配置实现 HTTPS 访问。核心需注意 80 端口占用、证书路径配置准确性,且务必补充 Nginx 重载逻辑,实现证书续期自动生效,整套方案轻量化易维护,彻底解决证书 90 天有效期的痛点。