How To Run NodeJS Applications in Production using PM2

In this tutorial, will learn how to run Node apps using a process manager named PM2.

Node has a built-in server for hosting JavaScript application’s based on it, such as Angular, React, and Vue. However, it is not a process manager. This means when you run your application using NPM or Node directly the application will not restart when problems are encountered.

Rather, the process will terminate until it is manually restarted. Obviously, this behavior is not desirable in any production environment.

To successfully run your Node-based application in production, such as an Express RESTful API, you will need to use what is known as a process manager. The most popular manager for Node applications is PM2, which doubles as a load balancer as well.

This tutorial will guide you through running your NodeJS applications in production with confidence.

Getting Started

PM2 is a publicly available service written for NodeJS. As with most JavaScript applications it can be installed via NPM. In order to do that we must install NodeJS and NPM prior to installing PM2.

Installing NodeJS

Install PM2

As mentioned above, PM2 is installed as an NPM module. The installation needs to be done globally to allow any Node application to be managed by it. Ensure you use the -g flag with npm to instruct it to perform a global installations of PM2.

sudo npm install -g pm2

Create a System Account for PM2

Like any service running on a production server, PM2 should run under its own user context. By doing so we eliminate a large security hole and minimize the amount of damage a hacker can do via a vulnerability in PM2.

When services running as root become compromised, a hacker will have full access to the server. They obtain root level privileges that permit them to do anything.

On the other hand, by running your service with an unprivileged user account, we significantly decrease our security footprint and the amount of damage that can be done.

The following command creates a service account named pm2. The -r flag is used to set the account as a system account, which provides an extra layer of security, such as not allowing log ons.

useradd -r -c "pm2 service account" pm2 

Service accounts should never be used for anything other than the service they were created for. It merely exists to run a process and nothing more. By using the -f flag, we remove the ability to remotely log in as the service account, which removes a possible attack vector.

Auto Starting PM2 at Boot

Run the following command to automatically start PM2 after a system boot. Not only will this command instruct systemd to run PM2 at boot, it will run it under the context of our previously generated pm2 system account within the pm2 account’s home directory.

sudo env PATH=%PATH/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u pm2 -hp /home/pm2

Running Your App from PM2

With PM2 installed we can now run our app. To do so the start command is used against a javascript file, which should be the entry script for the application.

pm2 start server.js

To view the status of applications running with PM2 you use the l command. The outputted table will give you a snapshot of the NodeJS application running in the background and its health.

pm2 l
┌──────────┬────┬─────────┬──────┬───────┬────────┬─────────┬────────┬──────┬───────────┬─────────┬──────────┐
 │ App name │ id │ version │ mode │ pid   │ status │ restart │ uptime │ cpu  │ mem       │ user    │ watching │
 ├──────────┼────┼─────────┼──────┼───────┼────────┼─────────┼────────┼──────┼───────────┼─────────┼──────────┤
 │ index    │ 1  │ 1.0.0   │ fork │ 23010 │ online │ 17      │ 4D     │ 0.2% │ 48.5 MB   │ vagrant │ disabled │
 │ server   │ 0  │ 1.0.0   │ fork │ 27127 │ online │ 16      │ 2D     │ 0.2% │ 61.0 MB   │ vagrant │ disabled │
 └──────────┴────┴─────────┴──────┴───────┴────────┴─────────┴────────┴──────┴───────────┴─────────┴──────────┘

The application name is derived from the file of the nodejs application used with the pm2 start command. This isn’t very useful if all of your applications start with index.js or server.js.

To set the application name when starting it you use the –name flag with pm2. For example, the following will start index.js with the name auth-api.

pm2 start index.js --name=auth-api

When running applications are listed now, a more descriptive name will be shown in the output.

┌──────────┬────┬─────────┬──────┬───────┬─────────┬─────────┬────────┬─────┬───────────┬─────────┬──────────┐
 │ App name │ id │ version │ mode │ pid   │ status  │ restart │ uptime │ cpu │ mem       │ user    │ watching │
 ├──────────┼────┼─────────┼──────┼───────┼─────────┼─────────┼────────┼─────┼───────────┼─────────┼──────────┤
 │ auth-api │ 2  │ 1.0.0   │ fork │ 28998 │ online  │ 0       │ 0s     │ 0%  │ 20.9 MB   │ vagrant │ disabled │
 └──────────┴────┴─────────┴──────┴───────┴─────────┴─────────┴────────┴─────┴───────────┴─────────┴──────────┘

Stopping Applications

When an application needs to be stopped, possibily for maintenance, the stop command is used with PM2. The application name must be referenced when doing so.

pm2 stop auth-api

When done, you can verify the status of the applications state by running the pm2 list command.

┌──────────┬────┬─────────┬──────┬───────┬─────────┬─────────┬────────┬─────┬───────────┬─────────┬──────────┐
 │ App name │ id │ version │ mode │ pid   │ status  │ restart │ uptime │ cpu │ mem       │ user    │ watching │
 ├──────────┼────┼─────────┼──────┼───────┼─────────┼─────────┼────────┼─────┼───────────┼─────────┼──────────┤
 │ auth-api   │ 0  │ 1.0.0   │ fork │ 0     │ stopped │ 16      │ 0      │ 0%  │ 0 B       │ vagrant │ disabled │
 └──────────┴────┴─────────┴──────┴───────┴─────────┴─────────┴────────┴─────┴───────────┴─────────┴──────────┘

Showing Information about Running Applications

The pm2 list command shows only the most basic information needed to understand an application’s state. This information is helpful most of the time, however, you may need more detailed data to understand the health of a running application.

To output detailed information, use the pm2 show command.

pm2 show auth-api

The output will look to what is displayed in the following screenshot. As you can see, it provides information about the project, as well as some basic metrics useful for troubleshooting.

PM2 show output
Output for pm2 show auth-api

Actively Monitoring Running Applications

While the pm2 show command is useful, sometimes you need to dive in a little deeper to understand how an application is behaving. The pm2 monit command allows you to monitor NodeJS applications in realtime.

pm2 monit
PM2 Monit command for realtime monitoring of NodeJS applications

Conclusion

With this tutorial, you have learned how to effectively and securely run a Node application on a production server. You have also learned how your application can be monitored and managed using PM2.

You have also learned how to reload with downtime, which increases your reliability and improves your user experience. Two things important in today’s highly agile world.