Ứng dụng Node.js dưới systemd
Cách chạy ứng dụng Node trên VDS để nó tồn tại qua việc ngắt SSH và khởi động lại máy: unit systemd, biến môi trường, log.
Cập nhật 23 tháng 8, 2026
Chạy thủ công node index.js sẽ chết cùng phiên SSH. Để ứng dụng chạy liên tục và tự khởi động lại sau khi reboot, hãy chạy nó như một dịch vụ systemd — đây là cơ chế có sẵn của hệ thống, nên bạn không cần cài thêm gì.
Chuẩn bị
Cài Node từ kho chính thức, không dùng gói cũ của hệ thống:
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node -v
Tạo một người dùng riêng — ứng dụng không được chạy dưới quyền root:
useradd -r -m -d /srv/app -s /usr/sbin/nologin appuser
chown -R appuser:appuser /srv/app
sudo -u appuser npm ci --omit=dev --prefix /srv/app
Dịch vụ systemd
Tệp /etc/systemd/system/myapp.service:
[Unit]
Description=My Node app
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/usr/bin/node /srv/app/index.js
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now myapp
systemctl status myapp
Restart=always sẽ khởi động lại tiến trình sau khi bị crash. EnvironmentFile là tệp KEY=value thuần, không có dấu ngoặc kép và không có export; hãy đặt quyền cho nó là 600, vì tệp chứa mật khẩu.
Đưa ra ngoài qua proxy
Ứng dụng chỉ nên lắng nghe trên 127.0.0.1:3000, và một web server có chứng chỉ sẽ phục vụ nó ra bên ngoài:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Để biết thêm chi tiết, xem reverse proxy và Let's Encrypt. Nếu ứng dụng lắng nghe trên 0.0.0.0, nó có thể bị truy cập từ internet, bỏ qua proxy và không được mã hóa.
Log và cập nhật
journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago" -p err
systemctl restart myapp
Đầu ra stdout tự động được ghi vào journal — bạn không cần thiết lập tệp log riêng hay xoay vòng log.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân |
|---|---|
status=203/EXEC | Sai đường dẫn đến node hoặc đến tệp trong ExecStart — hãy dùng đường dẫn tuyệt đối |
| Dịch vụ khởi động lại liên tục | Ứng dụng crash khi khởi động: kiểm tra journalctl -u myapp -n 50 |
EADDRINUSE | Một tiến trình chạy thủ công vẫn đang chạy: ss -tulpn | grep 3000 |
| Chạy được qua SSH, nhưng không chạy được dưới dạng dịch vụ | Thiếu biến môi trường — systemd không có chúng, hãy đặt chúng trong EnvironmentFile |
| Quá trình build hết bộ nhớ trên VDS-1 | Build cục bộ rồi tải bản build hoàn chỉnh lên máy |
Đừng đặt pm2 lên trên systemd. Hai trình giám sát trên một tiến trình sẽ gây nhầm lẫn: systemd coi tiến trình vẫn sống trong khi pm2 đang khởi động lại nó.