Triển khai ứng dụng Full-Stack (NestJS & React) trên VPS Linux với Nginx và PM2
Hướng dẫn toàn tập triển khai ứng dụng Full-Stack (NestJS & React) trên VPS Linux với Nginx và PM2
Việc đưa một ứng dụng từ môi trường Local lên máy chủ Production là một bước ngoặt quan trọng trong chu kỳ phát triển phần mềm. Để một hệ thống vận hành ổn định, có khả năng tự phục hồi và bảo mật, lập trình viên cần nắm vững các công cụ cốt lõi trên Linux. Bài viết này sẽ hướng dẫn bạn chi tiết cách thiết lập môi trường Node.js v22, cấu hình Reverse Proxy bằng Nginx và quản lý vận hành bằng PM2 cho dự án NestJS (Backend) và React (Frontend).
1. Chuẩn bị môi trường: Cài đặt Node.js v22 (LTS)
Node.js v22 mang đến nhiều cải tiến về hiệu suất xử lý và khả năng tương thích ES Modules. Để cài đặt trên Ubuntu/Debian, chúng ta nên sử dụng NodeSource để đảm bảo nhận được phiên bản mới nhất.
// Cấu trúc kiểm tra phiên bản môi trường trước khi Deploy
interface EnvSpecs {
nodeVersion: string;
requiredVersion: string;
os: string;
}
function checkEnvironment(specs: EnvSpecs): boolean {
const current = parseInt(specs.nodeVersion.split('.')[0]);
const required = parseInt(specs.requiredVersion.split('.')[0]);
if (current < required) {
console.error(`Lỗi: Yêu cầu Node.js ${specs.requiredVersion}. Hiện tại là ${specs.nodeVersion}`);
return false;
}
console.log("Môi trường hợp lệ. Bắt đầu quá trình Build...");
return true;
}
const deployEnv: EnvSpecs = { nodeVersion: "22.0.0", requiredVersion: "22.0.0", os: "Ubuntu 24.04" };
checkEnvironment(deployEnv);
Sử dụng lệnh sau trong terminal để cài đặt:
- Cập nhật hệ thống:
sudo apt update && sudo apt upgrade -y - Cài đặt Node.js:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs
2. Quản lý quy trình với PM2 - Đảm bảo Zero-Downtime
PM2 là bộ quản lý process mạnh mẽ nhất cho Node.js. Nó giúp ứng dụng NestJS của bạn tự động khởi động lại nếu gặp sự cố crash và hỗ trợ quản lý log tập trung.
// Cấu hình file ecosystem.config.js cho dự án NestJS
module.exports = {
apps: [{
name: "nestjs-backend",
script: "./dist/main.js",
instances: "max", // Chạy chế độ Cluster để tận dụng toàn bộ CPU Core
exec_mode: "cluster",
env: {
NODE_ENV: "production",
PORT: 3000
},
log_date_format: "YYYY-MM-DD HH:mm Z",
error_file: "./logs/error.log",
out_file: "./logs/out.log"
}]
}
Các lệnh PM2 quan trọng cần nhớ:
pm2 start ecosystem.config.js: Khởi chạy ứng dụng theo cấu hình.pm2 monit: Theo dõi mức tiêu thụ RAM/CPU của các tiến trình trong thời gian thực.pm2 save: Lưu danh sách tiến trình để tự khởi động cùng OS.
3. Cấu hình Nginx làm Reverse Proxy
Nginx đóng vai trò là "người gác cổng", tiếp nhận các yêu cầu HTTP/HTTPS từ người dùng và điều hướng chúng đến ứng dụng NestJS (Backend) hoặc phục vụ các file tĩnh của React (Frontend).
| Tính năng | Frontend (React) | Backend (NestJS) |
|---|---|---|
| Cơ chế phục vụ | Static File (HTML/JS/CSS) | API Proxy (Port 3000) |
| Nginx Directive | root /var/www/react-app/dist; |
proxy_pass http://localhost:3000; |
| Tối ưu hóa | Gzip Compression, Browser Caching | Rate Limiting, Header Security |
// Ví dụ cấu hình Nginx mô phỏng bằng TypeScript Interface
interface NginxConfig {
domain: string;
backendPort: number;
sslEnabled: boolean;
staticPath: string;
}
const webConfig: NginxConfig = {
domain: "api.example.com",
backendPort: 3000,
sslEnabled: true,
staticPath: "/var/www/frontend/dist"
};
console.log(`Đang cấu hình Proxy cho domain ${webConfig.domain} đến cổng ${webConfig.backendPort}`);
4. Quy trình Build và Tối ưu hóa React Frontend
Khác với Backend, React cần được biên dịch sang mã máy khách (Client-side code). Chúng ta thường sử dụng Vite để tối ưu hóa tốc độ build.
Sau khi chạy npm run build, toàn bộ mã nguồn sẽ nằm trong thư mục /dist. Bạn cần chuyển thư mục này lên VPS và trỏ Nginx vào đó. Lưu ý cấu hình try_files để hỗ trợ React Router:
/* Cấu hình Nginx cho React Router (Logic giả lập) */
const nginxTryFiles = "try_files $uri $uri/ /index.html";
// Dòng này đảm bảo khi người dùng F5 ở trang /dashboard, Nginx vẫn trả về file index.html
// thay vì báo lỗi 404.
5. Bảo mật hệ thống với SSL (Certbot) và Firewall
Một ứng dụng hiện đại bắt buộc phải chạy trên HTTPS. Chúng ta sẽ sử dụng Let's Encrypt thông qua công cụ Certbot.
- Cài đặt Certbot:
sudo apt install certbot python3-certbot-nginx - Kích hoạt SSL:
sudo certbot --nginx -d yourdomain.com - Cấu hình Firewall (UFW): Chỉ mở các cổng cần thiết như 80, 443 và cổng SSH tùy chỉnh.
// Hàm kiểm tra tính hợp lệ của Header bảo mật
function validateSecurityHeaders(headers: Record): boolean {
const requiredHeaders = ['strict-transport-security', 'x-frame-options', 'content-security-policy'];
return requiredHeaders.every(h => headers.hasOwnProperty(h));
}
const currentHeaders = {
'strict-transport-security': 'max-age=31536000',
'x-content-type-options': 'nosniff'
};
console.log(`Bảo mật đạt chuẩn: ${validateSecurityHeaders(currentHeaders)}`);
6. Quản lý Log và Giám sát sức khỏe hệ thống
Khi ứng dụng chạy trên Production, log là thứ duy nhất giúp bạn "vết" lại lỗi. Hãy sử dụng cấu hình xoay vòng log (Log Rotation) để tránh việc file log phình to làm đầy ổ cứng VPS.
PM2 hỗ trợ pm2-logrotate để tự động hóa việc này. Đồng thời, bạn nên thiết lập Cronjob để dọn dẹp các thư mục tạm (temp) định kỳ.
// Interface cấu hình Monitoring đơn giản
interface HealthCheck {
serviceName: string;
uptime: number;
memoryUsage: number; // MB
status: 'ALIVE' | 'DEAD';
}
function reportSystemStatus(check: HealthCheck) {
if (check.memoryUsage > 1024) {
console.warn(`Cảnh báo: Dịch vụ ${check.serviceName} đang ngốn quá nhiều RAM!`);
}
console.log(`Service: ${check.serviceName} | Uptime: ${check.uptime}s | Status: ${check.status}`);
}
reportSystemStatus({ serviceName: "NestJS-API", uptime: 86400, memoryUsage: 450, status: 'ALIVE' });
7. Kết luận: Checklist triển khai thành công
Để đảm bảo dự án Full-stack của bạn vận hành trơn tru trên VPS Linux, hãy luôn đi qua danh sách kiểm tra sau trước khi bàn giao:
- Biến môi trường (.env) đã được cấu hình riêng cho Production (DB, API Key)?
- Nginx đã cấu hình giới hạn dung lượng upload (client_max_body_size)?
- PM2 đã được thiết lập
startupđể tự chạy khi VPS reboot? - SSL Certificate đã được kiểm tra tính năng tự động gia hạn (Auto-renewal)?
- Các cổng database (PostgreSQL/MySQL) đã được đóng kín đối với truy cập từ ngoài?
Triển khai ứng dụng là một nghệ thuật phối hợp giữa Code và Infrastructure. Chúc bạn xây dựng được những hệ thống mạnh mẽ và ổn định!
