Nếu bạn có API, website SSR hoặc ứng dụng backend Node.js, chạy trực tiếp bằng `node app.js` chỉ phù hợp khi thử nghiệm. Khi đưa lên VPS, bạn cần một process manager để ứng dụng tiếp tục chạy sau khi thoát SSH, tự khởi động lại khi gặp lỗi và phục hồi sau reboot. Bài này hướng dẫn quy trình thực tế với Node.js và PM2 trên Ubuntu, tập trung vào cách triển khai dễ kiểm tra và không làm rối cấu trúc server.
1. Khi nào nên dùng PM2 trên VPS?
PM2 là process manager cho ứng dụng Node.js. Nó giúp bạn quản lý tiến trình, xem trạng thái, đọc log, restart app và thiết lập cơ chế khởi động lại sau reboot.
Mô hình cơ bản:
Client → Nginx hoặc reverse proxy → Node.js → PM2 → VPS Ubuntu
Nếu ứng dụng chỉ chạy thử trong vài phút, node app.js có thể đủ. Với production, PM2 hữu ích khi cần một quy trình quản lý process rõ ràng.
2. Kiểm tra VPS trước khi cài
Đăng nhập SSH và kiểm tra hệ điều hành:
cat /etc/os-release
uname -m
free -h
df -h
Nên bảo đảm VPS còn đủ RAM và dung lượng cho ứng dụng, dependency và log. Đừng chọn tài nguyên chỉ dựa trên số lượng file JavaScript; workload API, SSR, worker và WebSocket có thể rất khác nhau.
3. Cài Node.js theo phiên bản ứng dụng yêu cầu
Trước tiên kiểm tra project có file .nvmrc, package.json hoặc tài liệu chỉ rõ phiên bản Node.js hay không.
Sau khi cài Node.js bằng phương pháp phù hợp với môi trường của bạn, kiểm tra:
node -v
npm -v
Không nên tự động nâng Node.js trên production chỉ vì có phiên bản mới. Hãy kiểm tra compatibility của framework và dependency trước.
4. Đưa source code lên VPS
Một cấu trúc đơn giản:
/var/www/my-node-app/
├── package.json
├── package-lock.json
├── src/
└── .env
Nếu dùng user triển khai riêng, có thể đặt source trong home của user hoặc một thư mục /var/www có owner phù hợp.
Không commit .env, private key hoặc secret vào repository công khai.
5. Cài dependency
Đi vào thư mục ứng dụng:
cd /var/www/my-node-app
npm ci
npm ci phù hợp khi project có lockfile và bạn muốn cài đúng dependency đã khóa. Với project không có lockfile, dùng quy trình package manager tương ứng.
Nếu ứng dụng có bước build:
npm run build
Kiểm tra trước bằng cách chạy foreground:
npm start
Nếu app listen ở 127.0.0.1:3000, hãy mở terminal khác và kiểm tra:
curl -I http://127.0.0.1:3000
Chỉ chuyển sang PM2 sau khi ứng dụng chạy ổn ở foreground.
6. Cài PM2
Có thể cài PM2 global:
sudo npm install -g pm2
Kiểm tra:
pm2 -v
7. Chạy Node.js bằng PM2
Nếu entry point là app.js:
cd /var/www/my-node-app
pm2 start app.js --name my-node-app
Kiểm tra:
pm2 status
Nếu ứng dụng dùng script trong package.json:
pm2 start npm --name my-node-app -- start
Cách thứ hai hữu ích khi project có command khởi động riêng như npm start.
8. Kiểm tra process và log
Xem danh sách app:
pm2 list
Xem chi tiết:
pm2 show my-node-app
Xem log realtime:
pm2 logs my-node-app
Chỉ xem một số dòng gần nhất:
pm2 logs my-node-app --lines 100
Nếu app tự restart liên tục, đừng chỉ restart tiếp. Hãy đọc log để tìm lỗi dependency, biến môi trường, port hoặc exception.
9. Thiết lập tự khởi động sau reboot
PM2 có thể tạo startup configuration:
pm2 startup
Lệnh sẽ in ra một command cần chạy với quyền phù hợp. Hãy chạy đúng command mà PM2 cung cấp, sau đó lưu process list:
pm2 save
Kiểm tra lại sau khi reboot:
sudo reboot
Sau khi SSH lại:
pm2 status
Không nên coi pm2 save là backup source code. Nó chỉ lưu danh sách process/config để PM2 phục hồi.
10. Đặt biến môi trường cho ứng dụng
Ví dụ app cần:
NODE_ENV=production
PORT=3000
DATABASE_URL=...
Không nên hard-code secret trong source. Bạn có thể quản lý environment bằng cơ chế phù hợp với deployment của mình.
Nếu thay đổi biến môi trường, cần reload/restart process để app nhận giá trị mới:
pm2 restart my-node-app
11. Chạy nhiều ứng dụng Node.js trên một VPS
PM2 cho phép đặt tên riêng:
pm2 start app.js --name api
pm2 start server.js --name frontend
pm2 start worker.js --name worker
Sau đó:
pm2 status
Tuy nhiên, nhiều process không có nghĩa VPS có thể chạy vô hạn workload. Hãy theo dõi RAM, CPU và số kết nối thực tế.
12. Dùng ecosystem file để quản lý deployment
Khi có nhiều thiết lập, tạo ecosystem.config.js:
module.exports = {
apps: [{
name: 'my-node-app',
script: './app.js',
instances: 1,
exec_mode: 'fork',
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
Khởi động:
pm2 start ecosystem.config.js
Đây là cách dễ đọc hơn khi project có nhiều tham số.
13. Khi nào nên dùng cluster mode?
Nếu ứng dụng CPU-bound hoặc cần tận dụng nhiều core, PM2 có cluster mode. Nhưng không nên bật cluster chỉ vì VPS có nhiều vCPU.
Trước khi scale process, hãy kiểm tra:
- ứng dụng có state local không;
- session có lưu trong memory không;
- WebSocket có yêu cầu sticky session không;
- database có chịu được số connection tăng không;
- workload có thực sự bị giới hạn bởi một process hay không.
Scale process mà không kiểm tra dependency có thể làm hệ thống khó ổn định hơn.
14. Đưa Node.js ra Internet bằng Nginx
Thông thường không cần mở port 3000 public. Có thể để Node.js listen trên localhost và dùng Nginx làm reverse proxy.
Mô hình:
Internet → 443 → Nginx → 127.0.0.1:3000 → Node.js
Ví dụ phần proxy trong server block:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
Sau khi sửa, kiểm tra:
sudo nginx -t
sudo systemctl reload nginx
15. Cập nhật ứng dụng Node.js an toàn
Một quy trình đơn giản:
- backup hoặc bảo đảm có thể rollback;
- lấy source mới;
- kiểm tra dependency;
- chạy test/build;
- restart PM2;
- kiểm tra health endpoint và log.
Ví dụ:
git pull
npm ci
npm run build
pm2 restart my-node-app
pm2 logs my-node-app --lines 100
Không nên git pull trực tiếp vào production nếu quy trình deployment của bạn chưa kiểm soát migration và thay đổi cấu hình.
16. Xử lý lỗi PM2 thường gặp
App không start
Kiểm tra:
pm2 logs my-node-app --lines 200
pm2 show my-node-app
Port đã được sử dụng
Kiểm tra:
sudo ss -ltnp | grep ':3000'
App chạy nhưng Nginx trả 502
Kiểm tra app:
curl -I http://127.0.0.1:3000
pm2 status
Sau đó xem error log Nginx.
App restart liên tục
Xem log và kiểm tra memory:
pm2 logs my-node-app --lines 200
free -h
Có thể ứng dụng crash do config, dependency hoặc bị OOM. Không nên kết luận nguyên nhân chỉ từ việc process đã restart.
17. Checklist production
- Node.js version phù hợp project.
- Dependency được khóa bằng lockfile.
- Secret không nằm trong repository public.
- App chạy bằng user phù hợp, không cần root.
- PM2 quản lý process.
- PM2 startup đã cấu hình nếu cần.
- Node.js không mở public port nếu không cần.
- Nginx reverse proxy đã kiểm tra bằng
nginx -t. - Có log và cách xử lý khi app crash.
- Có backup và quy trình rollback.
- CPU/RAM/disk được theo dõi.
18. Kết luận
Chạy Node.js trên VPS không chỉ là cài Node rồi giữ một terminal SSH mở. Với PM2, bạn có thể quản lý process, log, restart và khởi động lại ứng dụng sau reboot theo một quy trình rõ ràng. Khi kết hợp Nginx reverse proxy, Node.js có thể chạy phía sau cổng web công khai thay vì mở trực tiếp port ứng dụng.
Điểm quan trọng nhất là triển khai theo từng lớp: kiểm tra app ở foreground, đưa vào PM2, cấu hình startup, đặt environment an toàn, sau đó mới kết nối reverse proxy và theo dõi tài nguyên.
Kết luận
Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.
Chưa biết nên chọn gói nào?
Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.
Xem bảng giá VPS →