Deploy and run .NET applications on Windows Server VPS

You have a .NET application, maybe an ASP.NET Core API, a background service, or a legacy .NET Framework app, and you need to run it on a Windows Server VPS. This guide walks through exactly that: from installing the .NET runtime on a fresh Windows Server instance, to publishing your app, to configuring IIS as a reverse proxy in front of Kestrel. Every step includes the actual commands and paths. By the end, you will have a running .NET application reachable on port 80 or 443.
Prerequisites
- A Windows Server VPS running Windows Server 2022 or 2019. This guide uses Windows Server 2022.
- Administrator access (RDP into the server).
- Your .NET application source code (either compiled for deployment or ready to build).
- Optional but recommended: a domain name pointed at your server’s IPv4, if you want HTTPS.
- Basic familiarity with RDP, PowerShell, and IIS Manager.
在 Windows VPS 上部署 .NET 应用,建议使用 IIS 反向代理 Kestrel,以获得生产级别的稳定性和安全性。
When deploying .NET applications on a Windows VPS, it is recommended to use IIS as a reverse proxy for Kestrel to achieve production-grade stability and security.
Why run .NET on a Windows VPS instead of a container or Linux?
Since .NET Core, the runtime has been cross-platform, and many teams deploy their .NET apps on Linux containers. But there are still valid reasons to use a Windows Server VPS. First, if you have a legacy .NET Framework application that cannot run on Linux, Windows Server is the only option. Second, some enterprises mandate Windows Server for compliance or Active Directory integration. Third, you may need tight integration with IIS features like Windows Authentication, Application Request Routing (ARR), or custom modules. A Windows VPS gives you the full .NET ecosystem without compromise, at the cost of higher memory usage and a larger OS footprint.
Step 1, Install the .NET Runtime and Hosting Bundle
The .NET Hosting Bundle includes the .NET Runtime, ASP.NET Core module, and IIS integration. Install it and IIS will automatically detect and host ASP.NET Core applications.
Open an RDP session to your Windows VPS, launch PowerShell as Administrator, and run:
# Download the .NET 10 Hosting Bundle (adjust version if needed)
Invoke-WebRequest -Uri "https://dotnet.microsoft.com/download/dotnet/thankyou/runtime-aspnetcore-10.0-windows-hosting-bundle-installer" -OutFile "$env:TEMP\dotnet-hosting.exe"
# Run the installer silently
Start-Process -FilePath "$env:TEMP\dotnet-hosting.exe" -ArgumentList "/install", "/quiet", "/norestart" -Wait
# Verify installation
dotnet --info
The /quiet flag suppresses the GUI. If the installer requires a reboot, restart the VPS before continuing. After the reboot, run dotnet --list-runtimes to confirm the runtime is present, you should see a line like Microsoft.AspNetCore.App 10.0.x and Microsoft.NETCore.App 10.0.x.
Note for .NET Framework apps only: If you are running a legacy .NET Framework app (e.g. ASP.NET MVC 5), you do not need the Hosting Bundle. Windows Server includes .NET Framework 4.8 by default. You just need to ensure the Web Server (IIS) role and ASP.NET 4.8 feature are enabled, which we cover in Step 3.
Step 2, Publish your .NET application for deployment
On your development machine (or directly on the VPS if you have the SDK), publish the application as a self-contained or framework-dependent deployment. For a production VPS, a self-contained deployment is simpler because it bundles the runtime and does not depend on the exact version installed on the server.
# On your dev machine, inside the project directory
dotnet publish -c Release -o ./publish --self-contained true -r win-x64
Flags explained:
-c Release— builds in Release mode with optimizations.--self-contained true— includes the runtime so you don’t need to install it on the server separately.-r win-x64— target the Windows x64 platform.
Copy the entire ./publish folder to the VPS via RDP file copy, or use scp if you have SSH enabled on the server. Place it under C:\inetpub\wwwroot\YourApp or any directory you prefer. For this guide we use C:\Apps\DotNetApp.
Step 3, Install IIS and the ASP.NET Core Module
If IIS is not already installed on the VPS, add it through PowerShell:
# Install IIS and required features
Install-WindowsFeature -Name Web-Server, Web-WebServer, Web-Common-Http, Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-Static-Content, Web-Http-Logging, Web-Request-Monitor, Web-Stat-Compression, Web-Filtering, Web-Asp-Net45, Web-WebSockets, Web-Mgmt-Console -IncludeManagementTools
This command installs the Web Server role plus the ASP.NET 4.8 feature and the management console. The ASP.NET Core Module (ANCM) was installed by the Hosting Bundle in Step 1, so it is already present. To verify it is installed, open IIS Manager, select your server node, and look for the “Module” icon, you should see AspNetCoreModuleV2 listed.
Step 4, Configure IIS Application Pool and Site
ASP.NET Core apps must run in an application pool configured for “No Managed Code”. This is because Kestrel handles the .NET runtime, not IIS. Open IIS Manager, create a new application pool:
- Name:
DotNetAppPool - .NET CLR version: No Managed Code
- Managed pipeline mode: Integrated
Then create a new site that points to your app folder:
- Site name:
DotNetSite - Physical path:
C:\Apps\DotNetApp - Binding: Type
http, IP AddressAll Unassigned, Port80(or5000for development). Assign the application pool to this site.
After creating the site, stop the default Default Web Site if it conflicts on port 80.
Step 5, Ensure the application runs behind IIS (web.config)
ASP.NET Core publishes a web.config file automatically. Open C:\Apps\DotNetApp\web.config and verify it contains the ASP.NET Core Module handler:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\YourApp.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
The processPath points to your application’s executable. If you use a framework-dependent deployment, point it to dotnet.exe and the DLL path instead.
Verify: Browse to http://your-vps-ip, you should see your application. If you get a 502.5 or 500.30 error, check the stdoutLogFile path and enable stdout logging temporarily to see the startup errors.
Step 6, Configure HTTPS (optional but recommended)
For production, bind a certificate to your site. If you have a domain and a valid SSL certificate (for example, a GoGetSSL wildcard certificate), bind it in IIS Manager under site bindings. For a quick test, you can use a self-signed certificate:
# Create a self-signed certificate in PowerShell
New-SelfSignedCertificate -DnsName "yourdomain.com", "localhost" -CertStoreLocation "cert:\LocalMachine\My"
# Get the thumbprint and bind it via netsh
$cert = Get-ChildItem -Path "cert:\LocalMachine\My" | Where-Object {$_.Subject -like "*yourdomain.com*"}
netsh http add sslcert ipport=0.0.0.0:443 certhash=$($cert.Thumbprint) appid="{214124cd-d05b-4309-9af9-9caa44b2b74a}"
Then add an https binding in IIS Manager on port 443 and select the certificate.
Troubleshooting
502.5 Process Failure — This is the most common error. It means Kestrel failed to start. Check the Windows Event Viewer → Application logs for ASP.NET Core errors. Common causes: missing runtime (install the Hosting Bundle), wrong executable path in web.config, or a missing dependency like Visual C++ Redistributable.
500.30 In-Process Start Failure — The app started but threw an unhandled exception during startup. Enable stdout logging in web.config (set stdoutLogEnabled="true") and read the log file.
Port already in use — If another process is using port 80, change your site’s binding to a different port, or stop the conflicting service (run netstat -ano | findstr :80 to identify it).
Application pool crashing — Ensure the application pool identity has read/execute permissions to the app folder. Set the pool to run as ApplicationPoolIdentity (default) and grant IIS AppPool\DotNetAppPool read rights on C:\Apps\DotNetApp.
FAQ
Can I run a .NET 8 app on a Windows Server VPS in 2026?
Yes, .NET 8 reaches end of support on November 10, 2026. It is still fully supported as of mid-2026, but plan to migrate to .NET 10 LTS soon. Install the .NET 8 Hosting Bundle specifically for that runtime version.
Do I need IIS, or can I run Kestrel directly on the VPS?
You can run Kestrel directly (e.g. run dotnet YourApp.dll in a terminal), but for production you should use IIS as a reverse proxy. IIS handles port 80/443 binding, SSL termination, logging, process management, and automatic restart if the app crashes.
How much RAM does a Windows Server VPS need for .NET?
A basic ASP.NET Core app with IIS and Windows Server 2022 needs at least 2 GB RAM to run, though 4 GB is more comfortable. A 2GB RAM Windows VPS works for low-traffic applications; for any real load, start at 4 GB.
Can I deploy a .NET Framework app (not Core) the same way?
Mostly yes, with one difference: you do not need the Hosting Bundle or the ASP.NET Core Module. Publish your .NET Framework app as a standard IIS web application, and configure the application pool with the .NET CLR version v4.0 (not No Managed Code).
Is there a cheaper way to test .NET on a VPS before buying?
Rent a monthly billing VPS, you pay for one month, test your deployment, and cancel if it does not fit. No long-term contract required.
What if my .NET app needs a database on the same VPS?
You can install SQL Server Express locally (free for 10 GB) or run PostgreSQL/MySQL on the same Windows VPS. For production with larger data, consider a separate database VPS.
Related articles
- Manage Windows VPS with PowerShell Remoting
- Install IIS and host websites on Windows Server VPS
- Migrating a legacy .NET app to a Windows VPS
- Secure RDP configuration for Windows VPS
- Sizing RAM for Windows Server VPS: why 2 GB is never enough
Windows VPS 上运行 .NET 应用部署指南
.NET 应用程序完全可以在 Windows VPS 上运行,推荐使用 IIS 作为反向代理来托管 Kestrel。先安装 .NET Hosting Bundle,然后通过 dotnet publish 发布应用,将输出文件夹复制到服务器,最后在 IIS 中创建站点并绑定应用程序池。注意应用程序池必须设置为"无托管代码",以兼容 ASP.NET Core 的运行模式。如果遇到 502.5 错误,检查事件查看器和 web.config 中的可执行路径。对于生产环境,建议绑定 SSL 证书并启用 HTTPS。


