Deployment
PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.
Remote Server
Let's start by describing how to use PM2 to setup a Node.js production environment on an Ubuntu 15.10 VPS.
Installing Git
Install the Git package which is required later when deploying our app to the server.
$ sudo apt install git
Installing Node.js
Create a new user called worker
which will be used for running and deploying Node.js applications.
$ sudo useradd -s /bin/bash -m -d /home/worker -c "web worker" worker
Set a password for it or install a SSH key so you will be able to log in over SSH.
Log to the remote server using the new user you just created. Go to Node Version Manager repository and follow the installation steps there.
Log out and log in again with the new user, then install the latest node.
$ nvm install 7
Installing PM2
SSH to the remote server with the new user and install the PM2 package.
$ npm install -g pm2
$ pm2 install pm2-logrotate
Now run the pm2 startup
. This will print out the command which we have to run as one of the sudo
users.
PM2 is not using an interactive
mode. We must enable that to be the default behavior. Open the ~/.bashrc
file and comment out the lines starting with a comment If not running interactively, don't do anything
.
Installing Nginx
Node.js applications do not have permission to run on port 80
. It's a common practice to use Nginx as a public gateway.
$ sudo apt update
$ sudo apt install nginx
Open the default server configuration file /etc/nginx/sites-available/default
and configure the server to forward all traffic on port 80
to the private address http://127.0.0.1:4444
at which our Node.js application will be available.
upstream app {
server 127.0.0.1:3000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
access_log /var/log/nginx/app.log;
location / {
root /home/worker/circletesting/current/public;
index index.html index.htm;
try_files $uri @app;
}
location @app {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://app;
}
}
Run sudo service nginx restart
to apply the changes.
Setting Environment Variables
Application secrets and configuration data should be served to the application through environment variables.
SSH to the server as user worker
, open ~/.bashrc
file and define the variables that you need at the top of the file (e.g. export NODE_ENV="production"
).
Git Repository Access
At this point we have to make sure, that the new user which we created earlier, has access to the the remote Git repository where our Node.js application is saved. This means that the new user can clone
the repository.
We should try to clone the repository to the /tmp
directory before we deploy our app.
Development Machine
Let's assume that we've already created a working HTTP server application. Configure it for deployment.
Install the dependencies.
$ npm install --save pm2@latest
Create a new file ecosystem.config.js
and add configuration.
module.exports = {
"apps": [
{
"name": "app",
"script": "npm",
"args" : "start",
"autorestart": true
}
],
"deploy": {
"production": {
"user": "worker",
"host": ["{server-ip}"],
"ref": "origin/master",
"repo": "{git-repository-path}",
"path": "{path-to-app}",
"ssh_options": ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
"post-deploy": "npm install --only=production && pm2 startOrRestart ecosystem.config.js"
}
}
}
Open the package.json
file and set the deploy script.
{
"scripts": {
"deploy": "pm2 deploy ecosystem.config.js"
},
}
Setup the application directory, deploy your code and save the state.
$ npm run deploy production setup
$ npm run deploy production