Skip to content
VDS · Website và máy chủ web

Ứ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ứngNguyên nhân
status=203/EXECSai đườ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
EADDRINUSEMộ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-1Build 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ó.