Running Node.js Apps as systemd Services on Linux: A Beginner's Guide

Md Saif ZamanMd Saif Zaman
3 min read

Managing background processes on Linux can be tricky without the right tools. If you’re deploying a Node.js application and want it to start on boot, recover from crashes, and log efficiently, then systemd is your best friend.

In this post, we’ll walk through how to run a Node.js app as a systemd service—with an automation script included.


What is systemd?

systemd is the default init system in most modern Linux distributions. It’s responsible for booting the system and managing services (also called units). It can:

  • Start services at boot time

  • Monitor and restart them on failure

  • Manage dependencies between services

  • Log output via journalctl

For Node.js developers, this means your app can become a first-class citizen of the Linux OS.


Why Use systemd for Node.js?

Running Node.js apps using systemd brings several advantages:

  • Automatic Startup: Start your app every time the server reboots.

  • Failure Recovery: Restart it if it crashes—automatically.

  • System-wide Logging: Log output to journalctl, making debugging easier.

  • Isolation: Manage your app as a standalone service, fully independent from your shell session.



Step-by-Step: Creating the Node.js Service

Step 1: Create Your Node.js Server

Start by writing a basic HTTP server:

mkdir -p /root/code/node
cd /root/code/node
nano server.js

Paste the following:

const http = require('http');
const hostname = '127.0.0.1';
const port = 3311;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Node app is running!');
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Test it with:

node server.js

Visit http://127.0.0.1:3311 to confirm it's running.


Step 2: Create the systemd Service File

Navigate to the systemd directory:

cd /etc/systemd/system/
nano node.service

Add this content:

[Unit]
Description=Start Node.js App
After=network.target

[Service]
ExecStart=/usr/bin/node /root/code/node/server.js
WorkingDirectory=/root/code/node
Restart=on-failure
RestartSec=5
KillMode=control-group

[Install]
WantedBy=multi-user.target

Make sure the ExecStart path matches your Node.js binary (which node).


Step 3: Enable and Start the Service

systemctl daemon-reload
systemctl enable node.service
systemctl start node.service

Check the status:

systemctl status node.service

You should see active (running) if all goes well.


Step 4: View Logs with journalctl

To tail logs in real time:

journalctl -u node.service -f

To see all historical logs:

journalctl -u node.service

Step 5: Test Automatic Restart

Simulate a crash:

  1. Find the PID:
ps aux | grep server.js
  1. Kill it:
sudo kill -9 <PID>
  1. Watch systemd restart it:
systemctl status node.service

The service should be automatically restarted thanks to the Restart=on-failure directive.


Automate It with a Shell Script

Save time by using this prebuilt script that sets up everything in seconds.

#!/bin/bash

NODE_DIR="/root/code/node"
SERVICE_FILE="/etc/systemd/system/node.service"
NODE_PATH=$(which node)

echo "Creating Node.js server..."
mkdir -p $NODE_DIR
cat > $NODE_DIR/server.js <<EOF
const http = require('http');
const hostname = '127.0.0.1';
const port = 3311;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Node app is running!');
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
EOF

echo "Creating systemd service..."
cat > $SERVICE_FILE <<EOF
[Unit]
Description=Start Node.js App
After=network.target

[Service]
ExecStart=$NODE_PATH $NODE_DIR/server.js
WorkingDirectory=$NODE_DIR
Restart=on-failure
KillMode=control-group

[Install]
WantedBy=multi-user.target
EOF

echo "Reloading systemd and enabling service..."
systemctl daemon-reload
systemctl enable node.service
systemctl start node.service

echo "Node.js systemd service status:"
systemctl status node.service --no-pager

Make it executable and run:

chmod +x setup_node_systemd.sh
sudo ./setup_node_systemd.sh

Summary

Integrating your Node.js applications with systemd gives you production-grade stability and control—without needing third-party process managers like PM2. You’ll benefit from automatic recovery, centralized logging, and simplified deployment.

Whether you're deploying to the cloud, a VPS, or your local server, this approach keeps your Node apps running reliably.

1
Subscribe to my newsletter

Read articles from Md Saif Zaman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Md Saif Zaman
Md Saif Zaman