Run node.js service with systemd

Dec 31, 2015 JavaScript System

Node.js as a running service is becoming more and more popular these days. One of the issues many developers face is how to ensure their node.js service starts automatically, and more importantly how to keep it running should it crash. Previously one had to install modules such as forever, and then create some auto-start script to start the daemon when the server booted.

Most Linux systems have recently switched to using systemd, which makes this process a lot simpler and more efficient, and means that we do not need forever any more.

Create the node.js server

For this example we will use a slightly modified “web server” of the example from the Node.js website:

const http = require('http');

const hostname = '0.0.0.0'; // listen on all ports
const port = 1337;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end("Hello World\n");
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

We will save this file (for example) as /opt/nodeserver/server.js. Verify the node server works

node /opt/nodeserver/server.js
Server running at http://0.0.0.0:1337/

Assuming it works, we will now create a systemd file to start this server as a service.

Systemd

Create the service file

Create /etc/systemd/system/nodeserver.service

[Unit]
Description=Node.js Example Server
#Requires=After=mysql.service       # Requires the mysql service to run first

[Service]
ExecStart=/usr/local/bin/node /opt/nodeserver/server.js
# Required on some systems
#WorkingDirectory=/opt/nodeserver
Restart=always
# Restart service after 10 seconds if node service crashes
RestartSec=10
# Output to journal
StandardOutput=journal
StandardError=journal
SyslogIdentifier=nodejs-example
#User=<alternate user>
#Group=<alternate group>
Environment=NODE_ENV=production PORT=1337

[Install]
WantedBy=multi-user.target

Enable the service

systemctl enable nodeserver.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nodeserver.service to /etc/systemd/system/nodeserver.service.

Start the service

systemctl start nodeserver.service

Verify it is running

systemctl status nodeserver.service
● nodeserver.service - Node.js Example Server
   Loaded: loaded (/etc/systemd/system/nodeserver.service; enabled)
   Active: active (running) since Thu 2015-12-31 09:29:35 NZDT; 7s ago
 Main PID: 8952 (node)
   CGroup: /system.slice/nodeserver.service
           └─8952 /usr/local/bin/node /opt/nodeserver/server.js

Dec 31 09:29:35 fileserver nodejs-example[8952]: Server running at http://0.0.0.0:1337/

Security / testing

Of course this service would run as root, which you probably shouldn’t be doing, so you can edit /etc/systemd/system/nodeserver.service to run it as a different user depending on your system. If you make any changes to the service file, you will need to do a

systemctl daemon-reload

before reloading the service:

systemctl restart nodeserver.service

I always suggest doing a systemctl status nodeserver.service after edits and a restart to ensure the service is running as expected.

Now finally we can test how systemd restarts the process if it unexpectedly dies (thanks Mark for the suggestion). We will manually “kill” the running process by finding its Process ID (pid), and note how systemd automatically restart it again:

ps -ef | grep server.js     # find the current pid
kill 12345                  # kill the process by its pid reported above
ps -ef | grep server.js     # notice node process is immediately respawned with a different pid

Comments