Chạy ứng dụng .NET trên VPS Windows Server chi tiết 2026

Bạn vừa thuê một VPS Windows Server để chạy ứng dụng .NET, nhưng khi publish project lên rồi mở trình duyệt thì chỉ thấy trang lỗi hoặc màn hình trắng. Đây là tình huống quen thuộc với hầu hết dev mới chuyển từ môi trường local sang server thật. Khác với máy tính cá nhân đã cài sẵn Visual Studio, VPS Windows Server mới chỉ có hệ điều hành trần, bạn phải tự cài .NET Runtime, cấu hình IIS hoặc Kestrel, rồi chỉnh lại connection string và biến môi trường. Bài này mình sẽ đi từng bước, từ server mới tinh đến lúc ứng dụng .NET chạy được qua HTTP, kèm cách xử lý các lỗi hay gặp nhất.
Yêu cầu trước khi bắt đầu
Để làm theo bài này, bạn cần chuẩn bị:
- Một VPS Windows Server bản 2019 hoặc 2022/2025 (bản LTSC, có giao diện desktop hoặc core đều được, nhưng desktop dễ thao tác hơn). Bạn có thể tham khảo dịch vụ VPS Windows có sẵn IPv4 riêng tại Việt Nam nếu chưa có server.
- Quyền Administrator trên server. Toàn bộ lệnh trong bài chạy bằng PowerShell mở ở chế độ Run as Administrator.
- Ứng dụng .NET đã được publish dạng self-contained hoặc framework-dependent. Nếu chưa có, bạn cần build trước trên máy local bằng lệnh
dotnet publish. - Port 80 (và 443 nếu dùng HTTPS) mở trên firewall Windows và firewall của nhà cung cấp VPS.
Vì sao nên chạy .NET trên Windows Server thay vì container Linux?
Nhiều dev đang chạy .NET trên Linux container vì nhẹ và rẻ, nhưng vẫn có những lý do chính đáng để chọn Windows Server. Thứ nhất, nếu ứng dụng dùng thư viện chỉ hỗ trợ Windows như Windows Authentication, Active Directory, hoặc các component COM, bạn gần như không có lựa chọn nào khác. Thứ hai, đội ngũ vận hành đã quen với IIS và Windows Server thì việc giữ nguyên hạ tầng giúp giảm rủi ro. Thứ ba, một số ứng dụng kế thừa (legacy) viết bằng .NET Framework 4.x bắt buộc phải chạy trên IIS, không chạy được trên Linux.
Với .NET 8 và .NET 10 (bản LTS mới nhất hiện tại), bạn vẫn có thể chạy trên Linux, nhưng nếu hạ tầng đã là Windows Server thì ASP.NET Core Hosting Bundle sẽ giúp IIS làm reverse proxy cho Kestrel, đây là kiến trúc mặc định và ổn định nhất trên Windows.
Bước 1 - Cài đặt .NET Runtime và Hosting Bundle
Đầu tiên, bạn cần cài .NET Runtime và ASP.NET Core Runtime. Cách nhanh nhất là dùng winget (Windows Package Manager) có sẵn trên Windows Server 2022/2025:
winget install Microsoft.DotNet.Runtime.8
winget install Microsoft.DotNet.AspNetCore.8
Nếu server không có winget hoặc bạn dùng Windows Server 2019, hãy tải trực tiếp từ trang chủ dotnet.microsoft.com. Bản cần tải là ASP.NET Core Runtime 8.x (hoặc 10.x nếu bạn dùng bản mới), chọn bản Windows Hosting Bundle, không phải bản SDK.
Sau khi cài, kiểm tra phiên bản bằng lệnh:
dotnet --list-runtimes
Kết quả mong đợi hiện danh sách runtime đã cài, ví dụ Microsoft.AspNetCore.App 8.0.x. Nếu lệnh dotnet không được nhận diện, bạn cần mở lại PowerShell hoặc đăng xuất/đăng nhập lại để PATH được cập nhật.
Bước 2 - Cài đặt và cấu hình IIS
IIS (Internet Information Services) là web server mặc định trên Windows Server. Để cài IIS kèm các module cần cho ASP.NET Core, chạy lệnh PowerShell:
Install-WindowsFeature -Name Web-Server, Web-Asp-Net45, Web-Mgmt-Console -IncludeManagementTools
Lệnh này cài IIS, hỗ trợ ASP.NET 4.x (cho ứng dụng cũ), và IIS Management Console để bạn có giao diện quản trị. Quá trình có thể mất vài phút, sau đó server tự động khởi động lại nếu cần.
Sau khi cài xong, mở trình duyệt truy cập http://localhost, bạn sẽ thấy trang mặc định của IIS. Điều này xác nhận IIS đã hoạt động.
Bước 3 - Tạo Application Pool riêng cho ứng dụng
Application Pool trong IIS cách ly từng ứng dụng, nếu một app crash thì app khác không bị ảnh hưởng. Bạn nên tạo pool riêng cho mỗi ứng dụng .NET thay vì dùng pool mặc định (DefaultAppPool):
Import-Module WebAdministration
New-Item -Path 'IIS:\AppPools\MyDotNetAppPool' -Force
Set-ItemProperty -Path 'IIS:\AppPools\MyDotNetAppPool' -Name 'managedRuntimeVersion' -Value 'No Managed Code'
Set-ItemProperty -Path 'IIS:\AppPools\MyDotNetAppPool' -Name 'startMode' -Value 'AlwaysRunning'
Điểm quan trọng: ASP.NET Core không chạy trong CLR của .NET Framework, nên managedRuntimeVersion phải là No Managed Code. Nếu để mặc định là v4.0, ứng dụng sẽ lỗi 500.30. Chế độ AlwaysRunning giúp pool khởi động ngay khi IIS bật, giảm thời gian phản hồi request đầu tiên.
Bước 4 - Publish ứng dụng và copy lên server
Trên máy local (đã cài .NET SDK), publish ứng dụng ở chế độ framework-dependent để giảm dung lượng:
dotnet publish -c Release -o ./publish
Tham số -c Release build ở chế độ Release, -o ./publish chỉ định thư mục xuất ra. Sau đó bạn copy toàn bộ thư mục publish lên server, ví dụ vào C:\inetpub\MyDotNetApp. Bạn có thể dùng Remote Desktop kéo thả, hoặc nén ZIP rồi giải nén trên server. Nếu ứng dụng cần biến môi trường (connection string, API key), bạn đặt chúng trong file appsettings.json hoặc dùng IIS Configuration Editor.
Bước 5 - Tạo website trong IIS trỏ đến thư mục publish
Giờ bạn cần khai báo website trong IIS. Có thể dùng giao diện IIS Manager, nhưng PowerShell nhanh hơn khi làm nhiều lần:
New-Item -Path 'IIS:\Sites\MyDotNetApp' -Binding @{protocol='http'; bindingInformation='*:80:'} -PhysicalPath 'C:\inetpub\MyDotNetApp'
Set-ItemProperty -Path 'IIS:\Sites\MyDotNetApp' -Name 'applicationPool' -Value 'MyDotNetAppPool'
Lưu ý: binding *:80: nghĩa là lắng nghe mọi hostname trên port 80. Nếu bạn có nhiều website trên cùng VPS, cần phân biệt bằng hostname, ví dụ mysite.com:80:. Khi đó phải trỏ DNS A record của domain về IP VPS.
Sau khi tạo website, truy cập http:/// từ trình duyệt. Nếu bạn thấy trang web hoạt động, xin chúc mừng. Nếu thấy lỗi, đọc tiếp phần xử lý sự cố bên dưới.
Bước 6 - Cấu hình HTTPS với chứng chỉ SSL
HTTP trần không an toàn cho production. Bạn cần gắn chứng chỉ SSL vào binding của website. Nếu chưa có chứng chỉ, bạn có thể dùng chứng chỉ SSL giá rẻ từ thueVPS hoặc tạo self-signed để test nội bộ.
Sau khi có file .pfx (bao gồm cả private key), import vào máy tính bằng lệnh:
$cert = Import-PfxCertificate -FilePath 'C:\path\to\cert.pfx' -CertStoreLocation 'Cert:\LocalMachine\My' -Password (ConvertTo-SecureString 'YourPassword' -AsPlainText -Force)
Rồi thêm binding HTTPS vào website:
New-Item -Path 'IIS:\Sites\MyDotNetApp' -Binding @{protocol='https'; bindingInformation='*:443:'; certificateStoreName='My'; certificateHash=$cert.Thumbprint} -Force
Để ý dấu -Force ở cuối nếu binding http đã tồn tại, nó sẽ giữ nguyên binding cũ và thêm binding mới. Sau đó kiểm tra bằng https://yourdomain.com.
Bước 7 - Kiểm tra và xử lý lỗi thường gặp
Dưới đây là 3 lỗi phổ biến nhất khi chạy .NET trên IIS và cách xử lý:
Lỗi 500.30 (InProcess Startup Failure)
Lỗi này nghĩa là ứng dụng .NET khởi động thất bại trong tiến trình IIS (w3wp.exe). Nguyên nhân hay gặp: thiếu runtime, version không khớp, hoặc cấu hình sai. Kiểm tra Windows Event Log:
Get-WinEvent -LogName 'Application' -MaxEvents 20 | Where-Object {$_.LevelDisplayName -eq 'Error'} | Format-List TimeCreated, Message
Thông báo lỗi cụ thể sẽ nằm trong log. Thường thì cài đúng ASP.NET Core Hosting Bundle là hết lỗi này.
Lỗi 502.5 (OutOfProcess Failure)
Lỗi này xảy ra khi chạy chế độ OutOfProcess và tiến trình dotnet.exe bị crash. Kiểm tra file log trong thư mục logs của ứng dụng (nếu cấu hình logging ra file) hoặc dùng dotnet MyApp.dll chạy trực tiếp trong cmd để xem lỗi thật:
cd C:\inetpub\MyDotNetApp
dotnet .\MyApp.dll
Nếu ứng dụng chạy được bằng lệnh này mà vẫn 502.5 trên IIS, kiểm tra lại quyền thư mục: tài khoản IIS AppPool\MyDotNetAppPool cần quyền Read & Execute trên thư mục ứng dụng.
Lỗi HTTP 403.14 - Forbidden
Lỗi này thường do IIS không tìm thấy file cấu hình web.config trong thư mục publish. Kiểm tra file web.config có tồn tại trong thư mục ứng dụng không, nó do lệnh dotnet publish tự sinh ra.
Câu hỏi thường gặp
Chạy .NET trên Windows Server cần cài Visual Studio không?
Không cần. Visual Studio chỉ dùng để phát triển, còn để chạy ứng dụng bạn chỉ cần ASP.NET Core Runtime (Hosting Bundle). Cài Visual Studio trên server làm tốn tài nguyên và tăng diện tích tấn công bảo mật.
Nên chọn .NET 8 hay .NET 10 cho production?
Nếu ứng dụng mới, chọn .NET 10 vì là bản LTS mới nhất, hỗ trợ đến năm 2028. Nếu ứng dụng đang chạy ổn định trên .NET 8, không cần nâng vội, bản này vẫn được hỗ trợ đến hết tháng 11/2026.
Ứng dụng .NET Framework 4.x có chạy được trên cùng VPS với .NET 8 không?
Được. Windows Server hỗ trợ song song .NET Framework 4.x và .NET 8/10. Chỉ cần tạo application pool riêng, pool cho .NET Framework để managedRuntimeVersion là v4.0, pool cho .NET Core/5+ để là No Managed Code.
VPS Windows Server 1GB RAM có chạy nổi ứng dụng .NET không?
Chạy được ứng dụng nhỏ, nhưng nên dùng tối thiểu 2GB RAM. Bản thân Windows Server đã ngốn khoảng 1-1.5GB, tiến trình dotnet của bạn cần thêm vài trăm MB. Nếu ứng dụng dùng Entity Framework hoặc xử lý file lớn, nên chọn gói 4GB RAM.
Có cách nào tự động deploy ứng dụng .NET lên VPS Windows không?
Có. Bạn có thể dùng GitHub Actions với self-hosted runner chạy trên Windows Server, hoặc dùng PowerShell script + Task Scheduler để kéo code từ Git rồi publish. Cách đơn giản nhất cho dự án nhỏ: tạo script .bat chạy git pull và dotnet publish, rồi lên lịch bằng Task Scheduler.
VPS Windows Server giá bao nhiêu?
Giá thuê VPS Windows Server tùy thuộc cấu hình và nhà cung cấp. Tại thueVPS, gói VPS Windows khởi điểm từ khoảng 189.000đ/tháng cho 1 vCPU, 2GB RAM, ổ NVMe, bạn có thể xem chi tiết tại bảng giá VPS.
Bài viết liên quan
- Quản lý VPS Windows bằng PowerShell Remoting
- Cài đặt IIS và host website trên Windows Server
- Cấu hình Remote Desktop an toàn cho VPS Windows
- So sánh hiệu năng VPS Linux và Windows


