Running a Node.js process on Debian as a Systemd Service

Multithreaded JavaScript has been published with O'Reilly!

This guide will teach you how to run your Node processes automatically on Debian (or even Ubuntu). This will mean that your processes can start when your server boots and that they will keep running in case of crashes.

Two years ago I wrote “Running a Node.js process on Debian as an init.d Service“. A few things have happened since them, most notably Debian switching from init.d to Systemd.

One cool feature about Systemd is that it comes with the ability to restart processes if they fail, in a variety of configurable ways. What this means is that unlike the old init.d method where we need a process manager such as Forever, we can simply write a line of configuration to restart when crashing.

First things first you'll need to choose a location to keep your application. On most Linux systems this means putting the code somewhere under /var. However, another recent Debian change is the addition of a new /srv directory, intended to keep files served by the OS. For correctness we'll make use of that directory. Personally I like to create a /srv/www for keeping files served by a webserver (e.g. Nginx), and a separate /srv/node for keeping node services. With that in mind, let's use the following directory:

/srv/node/my-test-service

Your application, assuming it is a web app, should be written in such a way that it accepts a port number and interface via configuration (even if you think it's overkill it's a good habit to get into). These configuration options can be passed in via CLI arguments, but in general it's better to use environment variables (CLI arguments can be easily inspected). Database connection settings are also good candidates for Environment variables.

Here's an example of how to access environment variables using Node:

const server = new hapi.Server();
const port = process.env.MY_PORT || 3000;
const host = process.env.MY_HOST || '127.0.0.1';
server.connection({
  port,
  host
});

And if you want to read those same variables (such as for testing), you can precede your commands with the variables like so:

$ MY_PORT=3000 MY_HOST=localhost node my-test-service/index.js

With your application written in such a way to accept environment variables for configuration, let's now create a systemd service file:

$ vim /lib/systemd/system/my-test-service.service

One thing you can do with Systemd is specify other services which need to run first. In the case of a simple web application we want to wait for networking to be available (for more complex applications you way want to wait for services like MySQL to run as well). We also want the simple behavior of restarting the application when it crashes.

Here's a Systemd service file adhering to this criteria:

[Unit]
Description=My Test Service
After=network.target

[Service]
Environment="MY_HOST=0.0.0.0"
Environment="MY_PORT=80"
Type=simple
ExecStart=/usr/local/bin/node /srv/node/my-test-service/index.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

Once that file has been created you'll want to reload the Systemd daemon and then start our new service:

$ sudo systemctl daemon-reload
$ sudo service my-test-service start

There are other subcommands we can run than start, such as restart and stop. Other Debian services can also be controlled in this manner like mysql and nginx.

In a future post I'll show how I configure Nginx to serve up many different Node and PHP applications.

Tags: #nodejs #linux
Thomas Hunter II Avatar

Thomas has contributed to dozens of enterprise Node.js services and has worked for a company dedicated to securing Node.js. He has spoken at several conferences on Node.js and JavaScript and is an O'Reilly published author.