How to Run a Node.js App as a systemd Service on Linux
Running your Node.js app as a systemd service makes Linux itself keep it alive β starting it on boot, restarting it if it crashes, and managing its logs β without any extra tools. It is a clean, dependency-free alternative to PM2 on a VPS.
When to choose systemd over PM2
systemd is built into modern Linux, so there is nothing to install, and it integrates with the system's logging and boot process. PM2 offers easier clustering and a friendlier CLI. Both are valid; systemd appeals when you want minimal dependencies and native integration.
Creating the service file
Create a unit file at /etc/systemd/system/myapp.service:
[Unit]
Description=My Node App
After=network.target
[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node app.js
Restart=always
User=nodeapp
EnvironmentFile=/var/www/myapp/.env
[Install]
WantedBy=multi-user.target
Enabling and starting
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
enable makes it start on boot; --now starts it immediately. Restart=always brings it back if it crashes.
Managing and viewing logs
- Status:
systemctl status myapp - Logs:
journalctl -u myapp -f(pairs well with structured logging) - Restart:
systemctl restart myapp
Put Nginx in front for SSL and the public port. Run as a non-root user for security.
Frequently asked questions
systemd or PM2?
systemd for native, dependency-free process management; PM2 for easier clustering and a richer CLI. Many run PM2 itself under systemd. Either keeps your app alive and starting on boot.
How do I load environment variables?
Use EnvironmentFile= pointing to your .env, or Environment= lines in the unit. Keep that file readable only by the service user, since it holds secrets.
Should the service run as root?
No β set User= to a dedicated non-root account. Running as root is an unnecessary risk; a limited user contains the damage if the app is compromised.
Was this article helpful?