Automatically Start Node.js Applications When Your Raspberry Pi Boots Up

September 1, 2021 | 6 minutes
TL;DR: You can use PM2 to automatically start Node.js applications when a Raspberry Pi starts up.

When writing Node.js applications to run on a Raspberry Pi, it’s pretty straightforward to start them while you’re logged into the Pi. You can use the terminal to navigate to the folder where the application is stored and run your command, like npm run start.

Processes running on a computer
Processes running on a computer

What happens when you need to reboot the Pi or if it temporarily loses power though? You have to manually go through the steps above again to get your application running. While doable, this step can be automated by configuring the application to run when the Pi boots by using a process manager called PM2.

What’s PM2?

PM2, which stands for Process Manager 2, is a process manager for Node.js applications. Process managers let you control the lifecycle of your application by providing a means to manage common tasks needed to keep your application running. This includes things like startup scripts, deployment management, logging, monitoring, hot reloading, and more.

PM2 is a popular process manager that offers all of the features above and then some. It has great documentation and is quick to get started with, which is why I’ve chosen to use it for a number of my applications.

Installing PM2

The PM2 CLI can be installed using npm by running the following in your terminal:

npm install pm2 -g

The -g means that the package will be installed globally on the Pi.

Using PM2 to Start a Node.js Application on Boot

Running the Application with PM2

The first step is to start the application using PM2. To do this, navigate to the application folder in the terminal. Then, choose the appropriate command from the two options below:

  • To start a file, you can use this command, pm2 start index.js, where index.js is the path to the file that you want to run.
  • To start a script defined in the package.json file for your application, you can use this command, pm2 start npm -- run [insert script name] --. For example, if you’ve defined a custom script in your package.json file called readSensors, you would run pm2 start npm -- run readSensors --.

The commands above will start your application using PM2, which allows you to then control them with PM2. You should see something like this in your terminal:

PM2 process information after starting an application
PM2 process information after starting an application

To make it easier to identify which applications PM2 is running, you can name them by passing a --name [insert app name] parameter to the pm2 start command. For example, to name my application “example-app”, I would use this command: pm2 start index.js --name example-app. The name is then displayed in the PM2 output table instead of the filename:

PM2 process information after starting an application and providing a name for the process
PM2 process information after starting an application and providing a name for the process

At this point, the application is just running within the current session. Before we can configure it to run on boot, we need to implement a boot strategy.

Implementing a PM2 Boot Strategy

PM2 uses a boot strategy so that it knows what to do when the computer starts up. It will automatically detect the correct boot strategy to use based on your computer. To initiate the process on your Raspberry Pi, enter the following command in the terminal within the folder for your application:

pm2 startup

After running the command above, you’ll see something similar to this in your terminal:

PM2 startup output
PM2 startup output

The example above is the output from running the pm2 startup command on my Mac. The first piece of data in the output is the init system that PM2 found, which is launchd in my case. On a Raspberry Pi, the init system found by PM2 will be systemd. The way that these two init systems are implemented differs, but they both handle the same two tasks: booting the system and loading and maintaining services. PM2 abstracts away the need to know the differences between init systems; it handles that for you.

The second piece of data in the output is a command that needs to be copy/pasted into the terminal and run. It adds a script to the $PATH that will start PM2 as the current user for the detected init system. Make sure that you run this command in your terminal.

As part of completing this step, PM2 will generate a file that’s executed when the system starts. On a Raspberry Pi, it will be located at /etc/systemd/system/pm2-pi.service and it contains an ExecStart command that tells the Pi to run the pm2 resurrect command on boot. The command will look similar to the following:

ExecStart=/home/pi/.nvm/versions/node/v14.15.1/lib/node_modules/pm2/bin/pm2 resurrect

When this command runs, it will load any PM2 processes (such as your application thread) that you have saved, which is what starts the application on boot.

Save Application Process to Run it With PM2 Resurrect

After completing the steps above, there’s just one more thing that you need to do in order to use PM2 to automatically start your application when the Pi boots up.

In your terminal, run the command pm2 save in order to save the currently running process for the application. After saving the process, PM2 will be able to run it using the pm2 resurrect command that was setup in the previous step.

And that’s it — you’re done! Your application will now start running whenever your Pi boots up.

Running Multiple Applications on Boot

You can repeat the steps above for each Node.js application that you’d like to automatically start when the Raspberry Pi boots.

Helpful PM2 Commands

We’ve just scratched the surface of what PM2 can do. There are lots of commands that you can use to manage your application’s lifecycle, which are described in the PM2 documentation.

Here are a couple of commands that come in handy though when working with startup scripts.

pm2 list — Shows a list of the processes that PM2 is currently running

Example output of pm2 list command; note that the output will show the status (“online”, “error”) for each process.
Example output of pm2 list command; note that the output will show the status (“online”, “error”) for each process.

pm2 stop [insert id] — Will stop the process that matches the id (run the list command to get the id)

Example output of pm2 stop 0 command
Example output of pm2 stop 0 command

pm2 start [insert id] — Will start the process that matches the id

Example output of pm2 start 0 command
Example output of pm2 start 0 command

pm2 delete [insert id] — Will delete the process that matches the id

Example output of pm2 delete 0 command
Example output of pm2 delete 0 command

pm2 logs [insert id] — Shows logs from the process that matches the id