Instantly share code, notes, and snippets.

Embed
What would you like to do?
Deploy Node.js Apps with Flightplan

##Setup your server (this would ideally be done with automated provisioning)

  • add a deploy user with password-less ssh see this gist
  • install forever npm install -g forever

##Install flightplan

  • npm install -g flightplan
  • in your project folder npm install flightplan --save-dev
  • create a flightplan.js file
var plan = require('flightplan');

var appName = 'node-app';
var username = 'deploy';
var startFile = 'bin/www';

var tmpDir = appName+'-' + new Date().getTime();

// configuration
plan.target('staging', [
  {
    host: '104.131.93.214',
    username: username,
    agent: process.env.SSH_AUTH_SOCK
  }
]);

plan.target('production', [
  {
    host: '104.131.93.215',
    username: username,
    agent: process.env.SSH_AUTH_SOCK
  },
//add in another server if you have more than one
// {
//   host: '104.131.93.216',
//   username: username,
//   agent: process.env.SSH_AUTH_SOCK
// }
]);

// run commands on localhost
plan.local(function(local) {
  // uncomment these if you need to run a build on your machine first
  // local.log('Run build');
  // local.exec('gulp build');

  local.log('Copy files to remote hosts');
  var filesToCopy = local.exec('git ls-files', {silent: true});
  // rsync files to all the destination's hosts
  local.transfer(filesToCopy, '/tmp/' + tmpDir);
});

// run commands on remote hosts (destinations)
plan.remote(function(remote) {
  remote.log('Move folder to root');
  remote.sudo('cp -R /tmp/' + tmpDir + ' ~', {user: username});
  remote.rm('-rf /tmp/' + tmpDir);

  remote.log('Install dependencies');
  remote.sudo('npm --production --prefix ~/' + tmpDir + ' install ~/' + tmpDir, {user: username});

  remote.log('Reload application');
  remote.sudo('ln -snf ~/' + tmpDir + ' ~/'+appName, {user: username});
  remote.exec('forever stop ~/'+appName+'/'+startFile, {failsafe: true});
  remote.exec('forever start ~/'+appName+'/'+startFile);
});

##Deploy!

  • fly staging or fly production

##Take it to the next level Run your node app as a system service so it runs after server reboots

@ecabrera1

This comment has been minimized.

ecabrera1 commented Mar 11, 2015

Flightplan fails and this is the error

localhost ● failed (null)
● Command exited abnormally on localhost

@PacmenCo

This comment has been minimized.

PacmenCo commented May 15, 2015

I get the same error.

@aconital

This comment has been minimized.

aconital commented Jun 2, 2015

I get same error :-/ localhost > 'rsync' is not recognized as an internal or external command,

@ashe540

This comment has been minimized.

ashe540 commented Jun 21, 2015

rsync is a linux command, so windows doesn't recognize it. You can give it a shot with cwRsync (https://www.itefix.net/cwrsync) if you're brave enough.

@ghost

This comment has been minimized.

ghost commented Aug 17, 2015

When installing locally your video shows "npm install fly --save-dev". Above you say "npm install flightplan --save-dev". Which one is it?.... seems to be flightplan thanks. Great tutorials! Keep it up

@gartenfeld

This comment has been minimized.

gartenfeld commented Feb 9, 2016

Where do you get the socket from?

@gartenfeld

This comment has been minimized.

gartenfeld commented Feb 9, 2016

Why sync the files to a tmp directory first then move them to home?

@andredelgado

This comment has been minimized.

andredelgado commented Feb 18, 2016

If I use system services, does the process restart if it crashes?

@marcioamr

This comment has been minimized.

marcioamr commented Feb 23, 2016

On Windows I've the error bellow:

C:\Program Files\Git>npm install -g flightplan
\

> fibers@1.0.9 install C:\Users\marcior\AppData\Roaming\npm\node_modules\flightplan\node_modules\fibers
> node build.js || nodejs build.js

-
C:\Users\marcior\AppData\Roaming\npm\node_modules\flightplan\node_modules\fibers>node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\.
.\node_modules\node-gyp\bin\node-gyp.js" rebuild --release
gyp ERR! configure error
gyp ERR! stack Error: spawn ENOENT
 ERR! stack     at errnoException (child_process.js:1001:11)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:792:34)
gyp ERR! System Windows_NT 6.1.7601
ERR! command "node" "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild" "--release"
gyp ERR! cwd C:\Users\marcior\AppData\Roaming\npm\node_modules\flightplan\node_modules\fibers
gyp ERR! node -v v0.10.32
gyp ERR! node-gyp -v v1.0.1
gyp ERR! not ok
Build failed
'nodejs' não é reconhecido como um comando interno
ou externo, um programa operável ou um arquivo em lotes.
npm ERR! fibers@1.0.9 install: `node build.js || nodejs build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the fibers@1.0.9 install script.
npm ERR! This is most likely a problem with the fibers package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node build.js || nodejs build.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls fibers
npm ERR! There is likely additional logging output above.

npm ERR! System Windows_NT 6.1.7601
npm ERR! command "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "-g" "flightplan"
npm ERR! cwd C:\Program Files\Git
npm ERR! node -v v0.10.32
npm ERR! npm -v 1.4.28
npm ERR! code ELIFECYCLE
npm ERR! not ok code 0
@danielvaughan

This comment has been minimized.

danielvaughan commented Mar 19, 2016

Yes in the video it says to do npm install fly --save-dev locally but it seems to need to be npm install flightplan --save-dev as above

@benstuijts

This comment has been minimized.

benstuijts commented Mar 19, 2016

Hi, great video and tutorial. Could you please create an other with the scenario of using flightplan from a Window's machine? Since Windows doesn't use the rsync command...

@ghost

This comment has been minimized.

ghost commented Aug 7, 2016

Thanks for the tutorial..! 👍
By using the package.json file for the name and the main file you can make the script even more generic!

const plan = require('flightplan');
const pkg = require('./package.json');

const username = 'deploy';
const tmpDir = pkg.name + '-' + new Date().getTime();

// configuration
plan.target('production', [
    {
        host: 'myHost',
        username: username,
        agent: process.env.SSH_AUTH_SOCK
    },
]);

// run commands on localhost
plan.local((local) => {
    local.log('Copy files to remote hosts');
    var filesToCopy = local.exec('git ls-files', { silent: true });
    // rsync files to all the destination's hosts
    local.transfer(filesToCopy, '/tmp/' + tmpDir);
});

// run commands on remote hosts (destinations)
plan.remote((remote) => {
    remote.log('Move folder to root');
    remote.sudo('cp -R /tmp/' + tmpDir + ' ~', { user: username });
    remote.rm('-rf /tmp/' + tmpDir);

    remote.log('Install dependencies');
    remote.sudo('npm --production --prefix ~/' + tmpDir + ' install ~/' + tmpDir, { user: username });

    remote.log('Reload application');
    remote.sudo('ln -snf ~/' + tmpDir + ' ~/' + pkg.name, { user: username });
});
@paradoxall

This comment has been minimized.

paradoxall commented Sep 30, 2016

if you are using express change ;)

  remote.exec('forever stop ~/'+appName+'/'+startFile, {failsafe: true});
  remote.exec('forever start ~/'+appName+'/'+startFile);

by

    remote.exec('cd ~/'+ appName  + '&&' + 'forever start ./bin/www', {failsafe: true});
    remote.exec('cd ~/'+ appName  + '&&' + 'forever stop ./bin/www');
@vishnutmohan

This comment has been minimized.

vishnutmohan commented Jan 9, 2018

I am always getting error while running flightplan. But when running the script directly is working. Any idea?

$ echo 'npm --production --prefix ~/node-app-1515514102251 install ~/node-app-1515514102251' | sudo -u ubuntu -i bash
bash: line 1: npm: command not found
● failed (127)
@ghost

This comment has been minimized.

ghost commented Jul 31, 2018

how to solved this
Permission denied (publickey).
localhost > rsync: connection unexpectedly closed (0 bytes received so far) [sender]

@hintonbradley

This comment has been minimized.

hintonbradley commented Oct 31, 2018

Hey! Good tutorial - thanks for making this.
All goes well until the very last step. When I attempt to push to production (fly production), I get an the following error:

✈ Running default:production
✈ Executing local task
localhost Copy files to remote hosts
localhost $ git ls-files
localhost ● ok
● Empty file list passed to transfer()

Anyone have any ideas? FYI: I'm running on a mac.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment