Quản lí ứng dụng Node.js trong Production với Systemd Service và Journalctl
Hướng dẫn triển khai ứng dụng Node.js, Go hoặc Python dưới dạng Systemd Service trên Linux: Tự động khởi động lại khi crash, quản lý biến môi trường, giới hạn bộ nhớ RAM và theo dõi log thời gian thực với Journalctl.

Tại sao nên dùng Systemd thay vì PM2 hoặc Nohup?
Khi chạy ứng dụng backend (Node.js, Express, NestJS, Go, Python FastAPI...) trên máy chủ Linux, bạn cần đảm bảo ứng dụng luôn chạy ngầm, tự khởi động lại khi gặp lỗi crash và tự động bật lên mỗi khi máy chủ VPS khởi động lại.
Nhiều lập trình viên mới thường sử dụng lệnh nohup node app.js & hoặc cài đặt công cụ quản lý PM2. Tuy nhiên, trong các môi trường doanh nghiệp lớn, Systemd (hệ thống khởi tạo và quản lí dịch vụ mặc định của Linux) mới là giải pháp tối ưu nhất:
- Không cần cài thêm thư viện phụ thuộc: Systemd được tích hợp sẵn ở mức nhân hệ điều hành Linux (PID 1).
- Quản lý tài nguyên mạnh mẽ: Tích hợp cgroups cho phép giới hạn trực tiếp CPU, RAM và số lượng tiến trình con (threads).
- Quản lý log tập trung: Tích hợp trực tiếp với
journaldvà tự động quay vòng file log (Log Rotation) chống tràn ổ đĩa. - Độ tin cậy tuyệt đối: Không bao giờ bị crash như các process manager tầng người dùng.
Trong bài viết này, chúng ta sẽ từng bước đóng gói một ứng dụng Node.js thành một dịch vụ Systemd Unit Service chuẩn Production.
1. Chuẩn bị thư mục ứng dụng và non-root user
Không bao giờ chạy ứng dụng web trực tiếp dưới quyền root. Chúng ta sẽ tạo một tài khoản dịch vụ hệ thống riêng (Service Account):
# Tạo user hệ thống không có quyền đăng nhập shell trực tiếp (ví dụ: nodeapp)
sudo useradd -r -s /bin/false -d /var/www/my-app nodeapp
# Tạo thư mục chứa mã nguồn ứng dụng
sudo mkdir -p /var/www/my-app
Giả sử file khởi động chính của ứng dụng nằm tại /var/www/my-app/dist/server.js hoặc index.js.
Phân quyền sở hữu thư mục cho user nodeapp:
sudo chown -R nodeapp:nodeapp /var/www/my-app
2. Quản lý Biến môi trường (.env) an toàn
Tạo file chứa các biến môi trường cấu hình tại /var/www/my-app/.env.production:
sudo nano /var/www/my-app/.env.production
Nội dung:
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://pgadmin:SuperPass@127.0.0.1:5432/my_db
REDIS_URL=redis://127.0.0.1:6379
JWT_SECRET=super_secret_jwt_key_here
Phân quyền bảo mật nghiêm ngặt (chỉ cho phép user nodeapp được đọc file này):
sudo chmod 600 /var/www/my-app/.env.production
sudo chown nodeapp:nodeapp /var/www/my-app/.env.production
3. Tạo file Systemd Service Unit (my-app.service)
Tạo file định nghĩa dịch vụ tại /etc/systemd/system/my-app.service:
sudo nano /etc/systemd/system/my-app.service
Dán cấu hình chuẩn Production hoàn chỉnh dưới đây:
[Unit]
Description=My Production Node.js Web API Service
After=network.target postgresql.service redis.service
Wants=network-online.target
[Service]
Type=simple
User=nodeapp
Group=nodeapp
WorkingDirectory=/var/www/my-app
# Đọc các biến môi trường từ file bảo mật
EnvironmentFile=/var/www/my-app/.env.production
# Lệnh thực thi ứng dụng (sử dụng đường dẫn tuyệt đối của node)
ExecStart=/usr/bin/node /var/www/my-app/dist/server.js
# Tự động khởi động lại khi ứng dụng bị crash
Restart=always
RestartSec=5s
# Giới hạn khởi động lại (tránh vòng lặp restart liên tục khi code có lỗi cú pháp)
StartLimitIntervalSec=60s
StartLimitBurst=5
# Giới hạn tài nguyên phần cứng (Memory Limit)
MemoryHigh=800M
MemoryMax=1024M
TasksMax=1000
# Tối ưu giới hạn file mở (File Descriptors) cho Web Server chịu tải cao
LimitNOFILE=65535
# Tăng cường bảo mật Sandbox
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
Giải thích các tham số quan trọng:
After=network.target postgresql.service: Đảm bảo dịch vụ mạng và cơ sở dữ liệu đã sẵn sàng trước khi ứng dụng khởi chạy.Restart=always&RestartSec=5s: Nếu ứng dụng bị Unhandled Exception dẫn đến crash, Systemd sẽ tự động khởi động lại sau 5 giây.MemoryMax=1024M: Giới hạn tối đa 1GB RAM. Nếu ứng dụng vượt quá mức này, Systemd sẽ tự động kill và restart lại dịch vụ để bảo vệ máy chủ.ProtectSystem=full: Ngăn ứng dụng ghi đè lên các thư mục hệ điều hành quan trọng như/usr,/boot,/etc.
4. Kích hoạt và Vận hành Dịch vụ
Mỗi khi tạo mới hoặc chỉnh sửa file .service, bạn cần yêu cầu Systemd nạp lại cấu hình:
sudo systemctl daemon-reload
Kích hoạt dịch vụ tự động khởi chạy cùng máy chủ:
sudo systemctl enable my-app
Bắt đầu khởi chạy dịch vụ:
sudo systemctl start my-app
Kiểm tra trạng thái hoạt động:
sudo systemctl status my-app --no-pager
Nếu màn hình hiển thị màu xanh lá cây Active: active (running) thì dịch vụ của bạn đã vận hành hoàn hảo!
5. Theo dõi và Giám sát Log với journalctl
Toàn bộ log console.log() và console.error() của ứng dụng Node.js sẽ được chuyển tiếp trực tiếp vào hệ thống quản lý log journald.
Dưới đây là các lệnh theo dõi log thông dụng:
# Xem log thời gian thực (giống tail -f)
sudo journalctl -u my-app -f
# Xem 100 dòng log gần nhất
sudo journalctl -u my-app -n 100 --no-pager
# Xem log ghi nhận trong ngày hôm nay
sudo journalctl -u my-app --since today
# Chỉ xem các log có mức độ cảnh báo hoặc lỗi (Warnings/Errors)
sudo journalctl -u my-app -p err..emerg
6. Quy trình triển khai Code mới (Zero-Downtime Deployment)
Khi bạn đẩy code mới lên máy chủ, quy trình triển khai diễn ra cực kỳ đơn giản và nhanh gọn:
# 1. Chuyển vào thư mục mã nguồn
cd /var/www/my-app
# 2. Kéo code mới và build
git pull origin main
npm ci --production
npm run build
# 3. Phân lại quyền cho user dịch vụ
sudo chown -R nodeapp:nodeapp /var/www/my-app
# 4. Khởi động lại dịch vụ mượt mà
sudo systemctl restart my-app
Bảng tra cứu lệnh Systemd thiết yếu
| Lệnh | Ý nghĩa |
|---|---|
sudo systemctl start <service> | Khởi động dịch vụ |
sudo systemctl stop <service> | Dừng dịch vụ |
sudo systemctl restart <service> | Khởi động lại dịch vụ |
sudo systemctl reload <service> | Nạp lại cấu hình mà không ngắt kết nối |
sudo systemctl enable <service> | Cho phép tự chạy khi bật máy |
sudo systemctl disable <service> | Tắt tính năng tự chạy |
sudo systemctl is-active <service> | Kiểm tra nhanh trạng thái (running/inactive) |
Lời kết
Sử dụng Systemd Service là giải pháp bản địa (native), nhẹ nhất, nhanh nhất và chuẩn mực nhất để đưa bất kỳ ứng dụng backend nào lên môi trường sản xuất Linux.



Đăng nhập bằng tài khoản GitHub để đặt câu hỏi hoặc đóng góp ý kiến cho bài viết.