Tài liệuỨng dụng .NET

Ứng dụng .NET

Cài .NET 8, 9 hoặc 10 SDK, deploy ASP.NET Core và ứng dụng web C# bằng dotnet publish, cho Kestrel lắng nghe trên $PORT qua ASPNETCORE_URLS và xử lý các lỗi thường gặp.

ZoPanel build ứng dụng web .NET bằng dotnet publish, chạy ứng dụng đã publish như một dịch vụ của tài khoản hosting và đặt nginx kèm SSL phía trước. Dùng cho ASP.NET Core (MVC, Razor Pages, Blazor Server, minimal API) và mọi ứng dụng .NET phục vụ HTTP.

Cài .NET SDK

Quản trị viên cài một lần cho mỗi server:

  1. Mở Runtime.
  2. Trên thẻ .NET SDK, bấm phiên bản cần cài (.NET 10.0, .NET 9.0 hoặc .NET 8.0). Log tác vụ hiển thị tiến trình cài. Hãy cài mọi phiên bản mà các ứng dụng của bạn nhắm tới: chúng được cài song song.

ZoPanel cung cấp các phiên bản SDK mà Microsoft còn hỗ trợ: .NET 10 (LTS, hỗ trợ đến tháng 11/2028), cùng .NET 9 và .NET 8, cả hai được hỗ trợ đến ngày 10/11/2026. Mỗi gói (dotnet-sdk-10.0, …) đã bao gồm ASP.NET Core runtime tương ứng:

Hệ điều hành Nguồn SDK Kiến trúc
Ubuntu 22.04 8.0 từ gói của Ubuntu; 9.0 và 10.0 từ kho .NET backports của Canonical (ppa:dotnet/backports), được thêm tự động amd64 và arm64
Ubuntu 24.04 8.0 và 10.0 từ gói của Ubuntu; 9.0 từ kho .NET backports amd64 và arm64
Debian 12, 13 Kho gói của Microsoft, được thêm tự động amd64: 8.0, 9.0, 10.0. arm64: chỉ 10.0

Quan trọng: Microsoft chỉ phát hành gói .NET 8 và .NET 9 cho Debian trên amd64. Trên server Debian arm64, thẻ chỉ cho cài .NET 10 và giải thích lý do; với ứng dụng nhắm net8.0 hoặc net9.0 trên server đó, hãy chuyển sang net10.0, dùng server Ubuntu, hoặc build và chạy ứng dụng dưới dạng container (xem Deploy bằng Docker). Nếu kho của Microsoft chưa có cấu hình cho bản Debian đang dùng, việc cài dừng với thông báo ".NET is not available for Debian … yet: … (deploy with a Dockerfile instead)".

SDK nào build ứng dụng

Ô Phiên bản của ứng dụng chọn SDK. Tự nhận diện đặt ô này theo <TargetFramework> của project (net9.0 → 9.0; với <TargetFrameworks>, lấy bản mới nhất). Khi build, ZoPanel thêm vào bản phát hành một file global.json cố định phiên bản SDK đó, nên log build ghi "Using the .NET 9.0 SDK". Nếu repository đã có global.json riêng (trong thư mục project hoặc thư mục cha), file đó quyết định và ZoPanel không thêm file nữa. Khi không có phiên bản, dùng SDK mới nhất đã cài.

Nếu SDK của phiên bản đó chưa được cài, deploy dừng với thông báo "the .NET 9.0 SDK is not installed (installed: …)". Hãy cài nó ở mục Runtime, hoặc đổi target framework của project.

ZoPanel nhận diện gì

Dự án được coi là .NET khi thư mục gốc có file .csproj, file .sln, hoặc có .csproj nằm sâu một cấp thư mục. Sau đó ZoPanel tìm project sâu tối đa hai cấp (ví dụ src/MyApp/MyApp.csproj), bỏ qua bin, obj và thư mục ẩn:

  • Ưu tiên project web (Microsoft.NET.Sdk.Web), gắn nhãn ASP.NET Core. Nếu không có, dùng project đầu tiên có Microsoft.NET.Sdk, gắn nhãn .NET.
  • Khi có nhiều project, log build ghi rõ project nào được publish.

Với project MyApp.csproj, các lệnh đề xuất là:

Ô Lệnh
Lệnh cài đặt dotnet restore 'MyApp.csproj'
Lệnh build dotnet publish 'MyApp.csproj' -c Release -o out --no-restore
Lệnh chạy ASPNETCORE_URLS=http://127.0.0.1:$PORT dotnet out/'MyApp.dll'

Việc nhận diện chạy theo thứ tự cố định: package.json, composer.json, Gemfile hoặc file build Java trong cùng thư mục được xét trước .NET. Nếu framework bị nhận sai, đặt Thư mục gốc là thư mục project, hoặc tắt Tự nhận diện và tự đặt lệnh. Procfile có dòng web: sẽ thay lệnh chạy.

Deploy ứng dụng .NET

  1. Ở Website → Thêm website, chọn Git deploy, nhập tên miền và repository. Xem Git deploy.
  2. Mở tab Deploy của website, kiểm tra Framework và các lệnh trong Build & chạy.
  3. Muốn sửa lệnh, tắt Tự nhận diện, sửa lệnh rồi bấm Lưu & deploy lại.
  4. Thêm cấu hình trong Biến môi trường.
  5. Bấm Deploy ngay.

Bản mới chỉ được đưa lên khi trả lời Đường dẫn health check (mặc định /) với mã dưới 500 trong vòng 90 giây. Trong lúc đó bản cũ vẫn chạy. Muốn build bằng SDK khác, tắt Tự nhận diện và chọn Phiên bản (xem SDK nào build ứng dụng).

Muốn deploy không qua Git, tạo website kiểu Node / Proxy, tải mã nguồn lên domains/<tên-miền>/source và chọn nguồn File đã tải lên (Quản lý file). Hãy tải mã nguồn chứ không phải thư mục publish: ZoPanel tự chạy restore và publish.

Cổng và URL

Kestrel phải lắng nghe tại 127.0.0.1, trên cổng trong biến PORT. Lệnh chạy đề xuất làm việc này bằng ASPNETCORE_URLS=http://127.0.0.1:$PORT. Giữ nguyên tiền tố đó khi sửa lệnh, và không ghi cứng URL ở nơi khác:

  • Bỏ các lời gọi UseUrls(...) và mục Kestrel:Endpoints trong appsettings.json: chúng ghi đè ASPNETCORE_URLS.
  • Không thêm endpoint HTTPS cho Kestrel. nginx lo SSL và nói chuyện với ứng dụng qua HTTP thường.

PORT khác nhau giữa hai slot blue/green (slot thứ hai dùng cổng gốc cộng 10000), nên đừng ghi số cổng vào cấu hình.

Phía sau nginx

nginx gửi kèm X-Forwarded-For và X-Forwarded-Proto. Để ứng dụng thấy IP thật của khách và giao thức https (cho redirect, cookie, callback OAuth), bật middleware forwarded headers ở đầu Program.cs:

using Microsoft.AspNetCore.HttpOverrides;

var app = builder.Build();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

Proxy nằm ở 127.0.0.1, địa chỉ mà ASP.NET Core mặc định tin cậy.

Tên assembly

Lệnh chạy giả định file DLL được publish trùng tên file project. Nếu project khai báo <AssemblyName>, sửa lệnh chạy thành out/<AssemblyName>.dll.

Biến môi trường

Các biến trong Biến môi trường dùng được khi build và khi chạy. ZoPanel đặt thêm PORT và HOST=127.0.0.1.

  • Tên biến gồm chữ, số và _, bắt đầu bằng chữ hoặc _, tối đa 64 ký tự. Giá trị nằm trên một dòng, tối đa 8.192 ký tự. Tối đa 200 biến.
  • Giá trị được lưu trong file chỉ root đọc được và được systemd truyền vào, không bao giờ nằm trên dòng lệnh.

ASP.NET Core đọc biến môi trường như cấu hình. Dùng hai dấu gạch dưới cho khoá lồng nhau:

Biến Khoá cấu hình
ConnectionStrings__Default ConnectionStrings:Default
Smtp__Host Smtp:Host
ASPNETCORE_ENVIRONMENT Tên môi trường (Production khi không đặt)

Với database MariaDB hoặc PostgreSQL tạo trong ZoPanel, dùng server 127.0.0.1. Xem Database.

Bộ nhớ

Ứng dụng, quá trình build và mọi thứ khác của tài khoản dùng chung RAM (MB) của gói. Tiến trình vượt giới hạn bị kernel dừng và ZoPanel khởi động lại ứng dụng. Khi deploy, quá trình build và khoảng thời gian ngắn bản cũ và bản mới chạy song song cùng cần bộ nhớ.

Project ASP.NET Core mặc định dùng server garbage collection, giữ nhiều bộ nhớ hơn theo số nhân CPU. Với gói nhỏ, chuyển sang workstation GC hoặc giới hạn heap bằng biến môi trường (giá trị heap viết ở dạng hexa):

DOTNET_gcServer=0
DOTNET_GCHeapHardLimit=0x20000000

0x20000000 là 512 MiB. Xem Gói hosting và giới hạn.

File và log

  • Ứng dụng chỉ ghi được trong thư mục home của tài khoản và thư mục /tmp riêng. Lưu file upload trong Đường dẫn lưu trữ cố định (ví dụ wwwroot/uploads) hoặc trong database: mỗi bản release là một thư mục mới, 5 bản gần nhất được giữ để Rollback.
  • Log ứng dụng trong tab Deploy hiển thị 400 dòng output console mới nhất. Bật Trực tiếp để theo dõi liên tục.
  • Output restore và publish của từng lần deploy nằm trong Tác vụ. Log nginx ở tab Nhật ký.

Xử lý sự cố

Thông báo hoặc hiện tượng Cách xử lý
"the .NET SDK is not installed — install it under Runtimes" Server chưa có SDK nào. Nhờ quản trị viên cài một phiên bản trên thẻ .NET SDK ở mục Runtime.
"the .NET 9.0 SDK is not installed (installed: …)" Project nhắm một phiên bản chưa có SDK. Cài nó ở mục Runtime, hoặc đổi target framework.
".NET 8.0 cannot be installed: Microsoft publishes .NET 8 and 9 packages for Debian on amd64 only…" Debian trên arm64. Dùng .NET 10, server Ubuntu hoặc container.
".NET is not available for Debian … yet" khi cài Microsoft chưa có kho cho bản Debian này. Dùng Ubuntu hoặc deploy bằng Dockerfile.
NETSDK1045: The current .NET SDK does not support targeting .NET 10.0 Phiên bản được đặt tay thành SDK cũ hơn target framework, hoặc global.json của repository cố định một SDK cũ hơn. Bật lại Tự nhận diện, hoặc sửa global.json.
A compatible .NET SDK was not found global.json của repository yêu cầu một phiên bản SDK chưa được cài. Cài phiên bản đó, hoặc nới rollForward trong global.json.
"The app did not respond on port … within 90s (it must listen on $PORT)" Kestrel lắng nghe chỗ khác (thường là localhost:5000, hoặc URL trong appsettings.json, UseUrls). Giữ ASPNETCORE_URLS=http://127.0.0.1:$PORT và bỏ các cấu hình endpoint khác.
"The app exited during startup" Xem Log ứng dụng. The application to execute does not exist nghĩa là tên DLL trong lệnh chạy sai (xem mục Tên assembly).
Redirect hoặc link sinh ra dùng http://, hoặc IP khách luôn là 127.0.0.1 Thêm middleware forwarded headers như trên.
Ứng dụng tự khởi động lại mà không có lỗi Tài khoản chạm giới hạn RAM. Đặt DOTNET_gcServer=0 hoặc DOTNET_GCHeapHardLimit, hoặc tăng RAM (MB) của gói.

Xem thêm


← Ứng dụng Java Website tĩnh và build front-end →