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.

Copy link

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.

Copy link

PacmenCo commented May 15, 2015

I get the same error.

@aconital

This comment has been minimized.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

gartenfeld commented Feb 9, 2016

Where do you get the socket from?

@gartenfeld

This comment has been minimized.

Copy link

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.

Copy link

andredelgado commented Feb 18, 2016

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

@marcioamr

This comment has been minimized.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

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.

Copy link

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