简介面向运维、网络管理及系统部署初学者这份资源聚焦Windows Server 2022 Web服务器的完整搭建过程解决从操作系统安装到网站正式发布期间的环境准备与配置问题。内容按“服务器安装、功能测试、网站挂载、DNS域名解析”四个阶段逐步展开既有安装介质准备、分区格式化、系统语言与许可协议选择等基础步骤也有网络连通性、硬件设备和操作系统状态的功能测试方法同时对网站目录创建、素材拷贝、端口规划以及DNS服务器安装和域名记录配置等易错环节做了说明适合作为实验操作或生产环境部署的参考笔记。包体为单个docx文档压缩包整体约1016KB体积小、便于本地查阅或打印学习。目前已有2758人学习说明该主题关注度较高。通过阅读可掌握从零搭建Web服务器的主线流程、验证思路和排错要点有效降低初次部署时的迷茫感。1. 在 Windows Server 2022 上搭 Web 服务器先搞清楚你要的到底是哪一种很多人拿到一台 Windows Server 2022第一反应是“装个 IIS把网页丢进去完事”。但真到了生产环境你会发现这个想法只对了一半。Windows Server 2022 上的 Web 服务器搭建核心不是“把服务跑起来”而是先回答三个问题你的站点是给谁用的、要扛多大流量、后端是 ASP.NET 还是 PHP 还是纯静态这三个问题直接决定你是用 IIS、Nginx 还是两者混合。我见过太多人在一台 2C4G 的服务器上装了 IIS 又装 Nginx然后让 Nginx 反代 IIS最后发现性能没上去排障还多了一层。也有朋友从 Linux 转过来习惯性先装 Nginx结果遇到 ASP.NET 应用才发现 Windows 上的 Nginx 没法直接跑 .NET 程序还得在前面再挂一层 IIS。所以这篇实战笔记我按最常见也是我认为最稳的思路来讲IIS 做主力承载 ASP.NET 与静态站点Nginx 做静态资源前置与简单负载均衡再配合 Windows Server 2022 自带的防火墙和远程管理工具把从零到能上线、能排查、能防误操作的整条路径走通。这篇适合两类人一类是从 Linux 转 Windows 的运维另一类是公司里被分配了“顺便管一下服务器”的后端开发。2. 用 IIS 在 Windows Server 2022 上把 ASP.NET 站点跑起来角色安装到站点绑定2.1 为什么 Windows Server 2022 上首选 IIS不是情怀是 .NET 生态Windows Server 2022 内置的 IIS 10.0 不是当年 IIS 6 那个老古董了。它支持 HTTP/2、QUIC需要额外配置、进程隔离、集中式证书管理而且和 AD、PowerShell、组策略的集成度是 Nginx 在 Windows 上完全比不了的。如果你的业务是 ASP.NET Core、Web Forms 或者老旧的 ASP.NET Framework 应用IIS 是唯一“装上就能跑”的正确选择——Nginx 在 Windows 上只能做反向代理它没法直接承载 .NET 运行时。另外一个非常实际的理由是运维习惯。很多 Windows 管理员对 IIS 管理器的图形界面很熟但对命令行和配置文件改动很抵触。IIS 管理器里能看到站点状态、绑定、应用程序池、请求筛选出了问题一眼能看到 503、404.4、500.19 这些状态码缘由。你可以借助 IIS 的日志和 Failed Request Tracing 慢慢排这在 Windows 生态里比你去翻 Nginx 的 error.log 更符合直觉。提示如果你只是做静态文件分发或者把后端 API 放在别处那 Nginx 也够用只要站点里出现 ASP.NET 字样就老老实实先把 IIS 立起来。2.2 安装 Web 服务器角色两条路一条 GUI一条 PowerShell最稳的图形界面做法是打开“服务器管理器”点“添加角色和功能”一路下一步到“服务器角色”勾选“Web 服务器(IIS)”。这一步会顺带装上静态内容、默认文档、ASP.NET 相关模块但如果你要跑 ASP.NET Framework 4.x还需要在角色服务里额外勾选“.NET Framework 4.7 或 4.8 功能”下的“ASP.NET 4.8”——这个选项藏在“应用程序开发”分类里默认不勾。要想可复现、方便写进自动化脚本我更推荐直接执行下面的 PowerShell。它是 Windows Server 2022 上安装 IIS 的“标准答案”注意我额外加了 ASP.NET 4.8 和 WebSocket 协议支持这两个是你跑现代 .NET 应用最容易踩的缺省坑。powershell以管理员身份运行 PowerShell 5.1 或 7.xInstall-WindowsFeature -Name Web-Server, Web-Asp-Net45, Web-WebSockets, Web-Mgmt-Console -IncludeManagementTools逻辑说明Web-Server装的是 IIS 核心服务Web-Asp-Net45对应 ASP.NET 4.8 支持这个 Feature 名字老但装的确实是 4.8Web-WebSockets让你以后部署 SignalR 或 WebSocket 长连接时不用再回来补装Web-Mgmt-Console是 IIS 管理器图形界面的依赖。-IncludeManagementTools会把常用的 IIS 管理工具一起装上省得后面发现少了 IIS 管理器还要单独装。装完以后顺手Get-Service -Name W3SVC确认一下“World Wide Web Publishing Service”处于运行状态。很多新手在这一步翻车看到 IIS 管理器能打开就以为装好了结果站点启动不了就是因为 W3SVC 服务被系统默认设成了手动启动或者被安全策略禁用。2.3 创建第一个站点物理路径、应用程序池与绑定参数这样配假设你的网站代码已经发布到D:\sites\myweb目录里有web.config、静态资源、bin 文件夹。用 IIS 管理器“添加网站”时站点名称填myweb物理路径选到上面那个目录绑定类型按需选http或https端口默认 80 或 443主机名可以填域名也可以先留空。不过我更习惯用 PowerShell 来做原因是可以精确控制应用程序池的 .NET CLR 版本和管道模式。你在 GUI 里漏选“无托管代码”或“集成管道”轻则应用启动 500.19重则页面出现“由于发生内部服务器错误无法加载请求的页面”。下面这个命令把常见问题一次堵死powershell Import-Module WebAdministration如果站点已存在可先移除避免端口冲突if (Get-Website -Name myweb -ErrorAction SilentlyContinue) { Remove-Website -Name myweb }创建应用程序池使用 .NET CLR v4.0集成管道模式New-Item -Path IIS:\AppPools\myweb -Force | Out-Null Set-ItemProperty -Path IIS:\AppPools\myweb -Name managedRuntimeVersion -Value v4.0 Set-ItemProperty -Path IIS:\AppPools\myweb -Name managedPipelineMode -Value Integrated创建站点默认绑定 8080 端口New-Website -Name myweb -PhysicalPath D:\sites\myweb -Port 8080 -ApplicationPool myweb参数说明-Port 8080是为了本地测试不和现有服务撞端口换绑 80 时直接把 8080 改成 80 即可。managedRuntimeVersion设置成v4.0是为了兼容 .NET Framework 4.8 编译的程序集如果站点是纯静态或者 ASP.NET Core 独立部署这里应该设成空值或No Managed Code否则模块加载会报错。managedPipelineMode选Integrated是当前主流应用的默认要求如果你在兼容老程序也许需要Classic不过那已经是十年前的历史了新站点一律集成。站点创建后访问受阻时会发现 80 端口常被占用。Windows Server 2022 默认会有 SQL Server Reporting Services如果你装了或者 W3SVC 自己的默认站点跟你抢 80。所以新建站点前我会先跑一行netstat -ano | findstr :80看监听者。如果被其他服务占了比较好的做法是直接给现有站点换端口而不是硬杀进程。2.4 目录权限里暗藏的“访问被拒”IUSR 和 IIS_IUSRS 不是一回事站点建好后浏览器打开很可能直接看到 403.3 或者 500.19。这不是你代码有问题而是 Windows 文件系统 ACL 没给。IIS 处理静态文件时以IUSR用户身份访问物理路径处理应用程序池工作时以应用程序池身份通常是IIS AppPool\myweb访问 DLL 和配置。很多人图省事给Everyone加了完全控制这是最常见的权限漏洞更恶心的问题是只给了IUSR结果 ASP.NET 在第一次编译时报无法写入临时目录。正确做法是打开物理目录的属性在安全选项卡里添加IIS_IUSRS组读取和执行、列出文件夹内容、读取再把应用程序池标识IIS AppPool\myweb加上“修改”权限。如果你站点里有上传功能还要给一个专门的上传子目录额外分配写权限不要整站开放写。这个动作我在每次部署时都用 PowerShell 做掉形成习惯powershell $path D:\sites\myweb $rule1 New-Object System.Security.AccessControl.FileSystemAccessRule(IIS_IUSRS, ReadAndExecute, ContainerInherit,ObjectInherit, None, Allow) $rule2 New-Object System.Security.AccessControl.FileSystemAccessRule(IIS AppPool\myweb, Modify, ContainerInherit,ObjectInherit, None, Allow)$acl Get-Acl $path $acl.SetAccessRule($rule1) $acl.SetAccessRule($rule2) Set-Acl -Path $path -AclObject $acl这个脚本里ContainerInherit,ObjectInherit决定权限会往下传给子目录和文件None表示不应用传播标志这样新创建的子目录也会继承。如果你的站点本来就是 500.19先检查web.config所在目录是否给了IIS_IUSRS读取权限再检查应用程序池对应的那个IIS AppPool\xxx有没有读web.config的权限。3. 让 Nginx 在 Windows Server 2022 上给 IIS 打工静态文件加速与反向代理3.1 什么时候需要 Nginx 前置照搬 Linux 方案前先想清这三件事Nginx 在 Windows Server 2022 上跑性能要比 Linux 版本打个折扣尤其是在连接并发高的情况下Windows 的 IOCP 模型跟 Nginx 的多进程模型不如 Linux epoll 那么和谐。但这不代表 Nginx 在 Windows 上没价值。我最常把它用在两个场景一是做静态资源服务器把图片、JS、CSS 从 IIS 里剥离出来减轻 IIS 的 CPU 负担二是做反向代理把客户端请求按路径转发给内网其他服务或同一台机器的不同端口同时利用 Nginx 的缓存做一层加速。做这个决定不要照搬 Linux 方案。你要先想清楚三件事第一你的并发是否真的高到 IIS 扛不住中小站点 IIs 单个应用程序池扛几千并发是没问题的Nginx 加进来多一层进程多一层复杂度第二你的站点是不是大量静态资源如果是视频、图片Nginx 的 sendfile 确实效率高第三你的团队在 Windows 上排障 Nginx 有没有经验如果出了问题只会看 Windows 事件日志那 Nginx 的配置文件错误就不太好查。3.2 下载解压与最小配置不用安装但目录别放 C 盘Nginx 在 Windows 上是绿色软件从官网下载 zip 包解压就能跑。发布包是nginx-1.26.x.zip解压后把文件夹整个挪到D:\nginx这种盘符不要放在C:\Program Files\nginx——因为 Nginx 在 Windows 上不注册为服务放在带空格的路径下部分命令行工具和后续定时重启脚本会踩引号转义的坑。我建议用一个名为nginx.conf的主配置里面只做两件大事监听 80 端口或者 8081 避免和 IIS 抢然后按路径把请求分发给后端 IIS。下面是一个最小可用的反向代理配置你复制后就能直接跑nginx worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65;server { listen 8081; server_name localhost; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { root D:/sites/myweb/static; expires 30d; add_header Cache-Control public; } }}这段配置的逻辑很清晰listen 8081是 Nginx 的对外入口location /把剩余请求全部转发给127.0.0.1:8080那正是 IIS 站点绑定端口。静态文件正则从D:/sites/myweb/static读绕开了 IIS。这里要特别说明Nginx 在 Windows 上路径分隔符最好用正斜杠/用反斜杠会偶尔解析异常expires 30d给静态资源加了一个月的浏览器缓存这一行能明显减少后端压力。提示proxy_set_header这几行不是装饰。IIS 里如果开了日志记录原始客户端 IP就必须把X-Forwarded-For传过去否则所有访问日志都会显示为 127.0.0.1后面的访问分析就废了。3.3 把 Nginx 注册成 Windows 服务网上下载的 WinSW 配置方式Nginx 自带包里的nginx.exe只能前台运行关掉控制台窗口进程就没了。所以我们必须借助常见做法——使用 WinSWWindows Service Wrapper来把 Nginx 注册成服务。先把 Nginx 解压后的目录放到D:\nginx再去 WinSW 项目页下载WinSW-x64.exe重命名为nginx-service.exe扔进D:\nginx。接着在同一个目录创建nginx-service.xmlxml nginx nginx Nginx Web Server on Windows Server 2022 D:\nginx\nginx.exe -p D:\nginx rotate配置里-p D:\nginx是告诉 Nginx 使用哪个前缀目录这样nginx.conf用相对路径访问 logs 和 temp 时才不会乱。logmode设为rotate让日志文件按日期轮转不然单文件无限增长会把磁盘塞满。然后以管理员身份执行bash cd /d D:\nginx nginx-service.exe install net start nginx如果安装成功再改配置流程是这样的先改conf\nginx.conf然后执行nginx -t检查语法没问题再执行nginx -s reload热加载。这几个命令很容易提前踩坑比如改了配置但没reload服务还在用旧配置半天看不出来。我一般会改完立刻用tasklist | findstr nginx确认主进程存在再访问页面验证效果。3.4 双服务端口分工清单别让 Nginx 和 IIS 在同一端口撞车Windows Server 2022 上 Nginx 与 IIS 共存最自然的口径就是 IIS 绑内网地址或 127.0.0.1 占用业务端口Nginx 绑公网入口 80/443 并转发内层 IIS。下面这张端口规划表是常见的分工方案你可以根据自己环境调整服务监听地址端口用途IIS 默认站点127.0.0.18080跑 ASP.NET 应用不对公网暴露Nginx0.0.0.080对公网提供 HTTP 入口转发到 8080Nginx可选项0.0.0.0443HTTPS 终结证书放在 Nginx 配置里如果公网端口 80 在你机器上已经被 IIS 的默认站点先占了你需要在 IIS 管理器里先把那个默认站点停止然后修改 Nginx 的listen为 80。另一个更常见的问题是 Nginx 在 Windows 上监听 443 与 IIS 的 443 冲突因为 IIS 默认也会监听 443此时要么让 IIS 只监听 127.0.0.1:443要么把 HTTPS 全部交给 NginxIIS 只保留 HTTP。我的经验是给 IIS 站点绑定都写死为 127.0.0.1公网走 Nginx这样改防火墙规则的时候边界更清晰。4. Windows Server 2022 安全加固与防火墙放行从裸奔到能上线4.1 系统自带防火墙与 IIS 请求筛选双管齐下的第一道闸很多教程让你“关闭防火墙方便测试”这是把服务器推向裸奔。Windows Server 2022 的防火墙默认对入站全拦截你装了 IIS 之后如果忘记放行HTTP服务局域网内其他机器仍然访问不了。最直接的放行方式是在高级安全 Windows 防火墙里新建入站规则允许 TCP 80 和 443 端口作用域建议只填“本地子网”或指定公网出口 IP而不是“任何”。同时IIS 的“请求筛选”也是个常被忽略的模块。在 IIS 管理器里选中你的站点双击“请求筛选”能看到“文件扩展名”、“请求限制”、“URL 限制”等选项。默认会拒绝.asp之外的某些危险扩展但 .NET 的.aspx在允许列表里。我通常会把“URL 长度限制”设置为 4096把“查询字符串限制”设置为 2048这样可以过滤掉一些明显的畸形请求也能避免长 URL 让后端日志膨胀。有精神的运维还会额外装 WAF那是另一层事情。先保证系统防火墙挡住非业务端口、IIS 请求筛选挡掉可疑后缀名再考虑更重的方案。4.2 SSL 证书绑定别再用 IIS 自签证书骗自己正确姿势是装完证书后做强制跳转生成自签名证书并绑定到 443 端口很容易但浏览器会提示不安全。生产环境还是用正规证书。Windows 的证书导入很简单在 IIS 管理器的“服务器证书”里点击“导入”选择 pfx 文件填好密码然后在站点绑定的编辑框里把“类型”改成 https端口 443证书指到你刚导入的那个。这步完成以后访问 https 能找到服务但如果你希望所有访问都走 HTTPS那就还需要设置 HTTP 到 HTTPS 的重定向。IIS 的 URL 重写模块可以帮你把 HTTP 请求重写到 HTTPSxml system.webServer /system.webServer这段配置是放在站点根目录的 web.config 里的。注意redirectTypePermanent是 301浏览器会缓存这个跳转如果后来你想暂时切回 HTTP这个 301 会让客户端一直走缓存清理起来很烦。所以我测试阶段常用Temporary(302)确认稳定了再改回Permanent。URL 重写模块需要单独安装Windows Server 2022 默认没带你要到微软官网下载rewrite_amd64_zh-CN.msi安装后重启 IIS 管理器和 W3SVC 服务才能生效。4.3 Windows 更新与账户策略别为了省事而禁用自动更新Windows Server 2022 与更早版本相比安全默认值高了比如 SMB 签名强制开启但系统补丁还是得靠自动更新。最稳妥的做法是组策略里设置成“自动下载并通知安装”而不是“完全关闭更新”。补丁常常包含对 IIS 和 .NET 运行时的安全修复长时间不打补丁的话即使企网内部也会被勒索病毒钻漏洞。另一个坏习惯是用 Administrator 跑所有站点和应用池。建议你创建独立的服务账户比如svc_web把它的“作为服务登录”权限开启然后给应用程序池的高级设置里把“标识”改为该账户。权限好用很多隔离性也强。如果不想创建域账户用本地账户也可以。但记得把该账户的密码设为永不过期否则某天你改密码并忘了改应用程序池的密码站点就会全部 503。5. 装完服务跑不起来的避坑与实战排查五个典型故障逐条拆解5.1 安装角色时提示“未安装必需的 Web 服务器角色服务: Windows 身份验证”有时候执行 Install-WindowsFeature 或通过添加角色向导时报错“未安装这些必需的 web 服务器角色服务: Windows 身份验证”。这不是因为你没选它而是因为在“角色服务”列表里默认没有勾选“Windows 身份验证”。这个模块对使用域账户集成认证的 Intranet 站点很重要但默认不启用。解决方式有两种。第一种重新进入添加角色向导在“Web 服务器(IIS) - 应用程序开发”或者「安全性」分类下勾选“Windows 身份验证”然后继续完成安装。第二种用 PowerShell 补装命令powershell Install-WindowsFeature -Name Web-Windows-Auth这一行安装完后会在 IIS 管理器中看到“身份验证”模块。需要注意的是Windows 身份验证和匿名身份验证是不能同时启用的你需要在站点级别或应用级别把“匿名身份验证”禁用否则浏览器不会弹登录框默认以匿名用户访问。5.2 访问站点出现 500.19配置错误还是权限不足先看事件查看器500.19是 IIS 处理 web.config 时出错的表现。最常见的原因是 web.config 所在的物理目录没有给应用程序池标识读取权限或者 web.config 里配置了当前 IIS 没安装的模块。遇到这个错误我会先打开“事件查看器”里的“Windows 日志 - 系统”看到来自 WAS 或 IIS-W3SVC-WP 的错误事件里面有详细错误描述。如果是权限直接参考上面 2.4 节用IIS_IUSRS和IIS AppPool\xxx设置目录 ACL。注意IIS_IUSRS是个组IUSR是单独的用户给错了照样报错。如果是模块缺失那就要检查 web.config 中是否引用了rewrite模块而你恰好没装 URL Rewrite。5.3 Nginx 启动后窗口一闪而过日志文件里面写明了原因Nginx 在 Windows 上双击 nginx.exe如果配置有误会显示一个黑窗口然后立刻消失。新手容易误以为“已经启动了”其实进程已经退出。此时看日志最直接进入D:\nginx\logs\error.log里面会写emerg级别的错误比如bind() to 0.0.0.0:80 failed说明端口被占用。如果你是修改配置后 reload 报错那就先执行nginx -t它会打印配置里第几行有问题。在我的经验里Windows 上最常见的 Nginx 配置错误是路径解析问题比如把D:/sites写成D:\sites或者写 root 路径时忘了加引号。老老实实按 Linux 上的习惯统一用正斜杠基本能避开一半问题。5.4 从局域网其他机器访问不到先 ping 通再查防火墙顺序不能乱一台 Windows Server 2022 装好 IIS本机能 curl 通 127.0.0.1但另一台机器访问超时。多数时候是防火墙阻挡。不要急着关闭防火墙先在本机执行ping 目标IP看网络通不通不通就查虚拟网络配置。网络通后在目标机上telnet IP 80看端口是否可连如果超时大概率防火墙入站规则未放行或者系统里装有第三方安全软件额外拦截。放行时优先在 Windows 防火墙里创建“入站规则”协议选 TCP端口选 80, 443作用域选“任何”。如果用了 Nginx 监听 8081也要把 8081 加进去注意 Nginx 服务监听的端口必须在防火墙里放行否则外部访问 Nginx 也超时。5.5 应用程序池频繁崩溃导致站点 503看事件日志里的“进程退出代码”ASP.NET 站点运行半小时左右就 503重启应用程序池能恢复但过会又崩。这种问题从 IIS 的事件日志能看出端倪——如果是进程w3wp.exe退出且退出代码是 0x80070005一般是权限问题如果是 0x8007007e则可能是 DLL 加载失败比如 64 位应用池跑 32 位程序集。解决思路先打开应用程序池的高级设置把“启用 32 位应用程序”按需调整再确保应用程序池的“回收”设置里“特定时间”没有设置得过频最后用“失败的请求跟踪”去抓 HTTP 500 错误的具体异常栈。如果还没方向进入“事件查看器 - 应用程序”里搜索.NET Runtime的报错那些信息比 IIS 日志直白得多。6. 把 IIS 与 Nginx 的日志统一收集定位真实访客与性能瓶颈生产中你早晚会遇到一个尴尬局面Nginx 记录了访问日志但里面的 IP 全是 127.0.0.1因为 IIS 才是后端源头真实 IP 存放在 Nginx 传来的X-Forwarded-For里。只盯着 Nginx access.log 做统计看到的永远是代理地址。解决当前问题的常用做法是在 Nginx 的 log_format 里加上$http_x_forwarded_for或在 IIS 里启用“X-Forwarded-For”日志字段。Windows Server 2022 的 IIS 自带日志模块支持自定义字段具体操作是在 IIS 管理器中选中站点点击“日志”选择“字段”在右侧添加X-FORWARDED-FOR。如果嫌 GUI 麻烦可以用 IIS 的logCustomFields配置节。另一个值得做的是把 Nginx 的access_log和 IIS 的W3SVC日志统一切割与归档。Nginx 在http块里定义nginx log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for;access_log logs/access.log main; access_log logs/access_json.log json;如果你和我的习惯一样喜欢把日志直接输送到 Elasticsearch 或 Loki 来透视全链路建议用 JSON 格式因为解析简单。Windows 上还要注意 Nginx 日志文件如果长期不切割会膨胀到几十 GB所以我在nginx-service.xml里设置了logmode rotate同时写了个计划任务在每天凌晨执行nginx -s reopen让 Nginx 重新打开日志文件这是业界成熟做法。验证这套日志方案是否有效的最直接方法用 curl 带一个自定义的X-Forwarded-For头访问 Nginx然后在 IIS 日志里看是否记录了这个头。如果记录正确说明从 Nginx 到 IIS 的全链路日志打通了后续做访问统计和排查恶意请求就有了依据。这套基本功做完你的 Windows Server 2022 Web 服务器才算真正从“能跑”进化到“能管、能查、能防”。我自己在每次交付前都会强制自己把日志链路测通因为等出问题再补日志就像做完了菜再找调料永远晚了半拍。希望这篇笔记能帮你把这条路走顺少踩几回我当年踩过的坑。本文还有配套的精品资源点击获取