Last Updated: February 25, 2016
· pstadler

Web applications in production: Flightplan + pm2 = <3

Updated November 22nd, 2014: code examples compatible with Flightplan >=0.5.0

With the combined power of pm2 and Flightplan, you're able to perform basic and advanced system administration tasks with ease.

pm2 is a process manager for node.js apps with a built-in load balancer.

Flightplan is a node.js library for streamlining application deployment or systems administration tasks.

I won't go into details about how to use pm2 at this point. Just head over to the pm2 repository on GitHub and read the documentation.

Installing Flightplan

Once you've set up your hosts to run your web apps with pm2, it's time to install Flightplan:

npm install -g flightplan // install globally to make the `fly` command available
npm install --save-dev flightplan // install for your current project


The next step is to create a file called flightplan.js in the root directory of your project and configure your enviroments:

var plan = require('flightplan');

// configuration
plan.target('staging', {
  host: 'staging.pstadler.sh',
  username: 'pstadler',
  agent: process.env.SSH_AUTH_SOCK

plan.target('production', [
    host: 'www1.pstadler.sh',
    username: 'pstadler',
    agent: process.env.SSH_AUTH_SOCK
    host: 'www2.pstadler.sh',
    username: 'pstadler',
    agent: process.env.SSH_AUTH_SOCK


Deploying your web app with Flightplan is painless. Below is the typical pattern of the deployment process of a modern web application:

// deployment
plan.local(function(local) {
  // 1) check repo status (e.g. dirty, branch, tagging, ...)
  // 2) build your project (e.g. gulp, grunt, ...)
  // 3) transfer files to remote hosts

plan.remote(function(remote) {
  // 4) move files, symlinking, etc.
  // 5) npm install --production
  // 7) pm2 reload

To deploy the app to either the staging or production enviroment, simply run fly staging or fly production. Check out this article on coderwall to learn more about Flightplan and how to deploy applications with it.


As of version 0.4.0, Flightplan supports tasks. Simply pass a string or an array of strings as the first parameter to plan.local() or plan.remote() to define them as tasks.

Now let's automate some things you would usually perform manually after connecting to your remote hosts, like checking you app's status or reloading it:

plan.remote('status', function(remote) { 
  remote.sudo('pm2 status', {user: 'www'});

plan.remote('start', function(remote) { 
  remote.sudo('pm2 start ~/sample-app/processes.json', {user: 'www'});
  // See also: https://github.com/Unitech/pm2#json-app-declaration

plan.remote('stop', function(remote) { 
  remote.sudo('pm2 stop sample-app', {user: 'www'});

plan.remote('reload', function(remote) { 
  remote.sudo('pm2 reload sample-app', {user: 'www'});

plan.remote('restart', function(remote) { 
  remote.sudo('pm2 restart sample-app', {user: 'www'});

Executing a specific task is as simple as calling fly <task>:<target>, for example: fly status:staging or fly reload:production.

If the <task> parameter is ommited, you're implicitly executing a task called default. With the setup we use in this article, calling fly staging would deploy our app to the staging environment.

Check out the official documentation of Flightplan here.

Having questions? You can find me on Twitter.