Automating deployments of Node.js application updates with shell scripts

If you have followed the Node.js deployment tutorial, then you know that deploying application updates takes multiple steps. Performing all these steps every time you want to deploy application updates is time-consuming and error-prone.

This guide teaches you how to automate the deployment of application updates with SSH and shell scripts. Once these scripts are set up, deploying further application updates only takes a single command.

Notes:

  • This guide assumes that you know how to manually deploy Node.js applications and how to manually deploy updates. This guide only makes sense if you have that prior knowledge. If you are not experienced in deploying manually, please read the Node.js deployment tutorial.
  • This guide assumes you are using at least Passenger 5.0.13. This guide does not work with earlier Passenger versions.

Table of contents

  1. Loading...

Basic idea

The goal of this automation guide is to create a set of scripts, so that when you want to deploy a new version of your application, you only have to git commit & push your changes and run the script.

We will create two scripts:

  • The deploy/work.sh script is run on the remote server. It performs all the steps that you would do manually on the server, such as running git pull, running npm install, restarting Passenger, etc.
  • The deploy/initiate.sh script is run locally. It performs all the steps that you would do manually on your local computer, such as running as SSH'ing into the server.

Creating deploy/work.sh

Create a deploy directory in your application directory. Inside there, create a work.sh which contains:

#!/bin/bash
set -e

### Configuration ###

APP_DIR=/var/www/myapp
GIT_URL=git://github.com/myusername/myapp
RESTART_ARGS=

# Uncomment and modify the following if you installed Passenger from tarball
#export PATH=/path-to-passenger/bin:$PATH


### Automation steps ###

set -x

# Pull latest code
if [[ -e $APP_DIR/code ]]; then
  cd $APP_DIR/code
  git pull
else
  git clone $GIT_URL $APP_DIR/code
  cd $APP_DIR/code
fi

# Install dependencies
npm install --production
npm prune --production

# Restart app
passenger-config restart-app --ignore-app-not-running --ignore-passenger-not-running $RESTART_ARGS $APP_DIR/code

Be sure to customize the APP_DIR and the GIT_URL configuration options. Set these to the actual application directory and Git repository URL, respectively.

Creating deploy/initiate.sh

Inside the deploy directory in your application directory, create an initiate.sh which contains:

#!/bin/bash
set -e

### Configuration ###

SERVER=myappuser@yourserver.com
APP_DIR=/var/www/myapp
KEYFILE=
REMOTE_SCRIPT_PATH=/tmp/deploy-myapp.sh


### Library ###

function run()
{
  echo "Running: $@"
  "$@"
}


### Automation steps ###

if [[ "$KEYFILE" != "" ]]; then
  KEYARG="-i $KEYFILE"
else
  KEYARG=
fi

run scp $KEYARG deploy/work.sh $SERVER:$REMOTE_SCRIPT_PATH
echo
echo "---- Running deployment script on remote server ----"
run ssh $KEYARG $SERVER bash $REMOTE_SCRIPT_PATH

Be sure to customize these configuration options:

  • Set APP_DIR to the actual application directory.
  • Set SERVER to the actual username and server name.
  • If your server is on Amazon EC2, set KEYFILE to the path of your EC2 key file.

Make this file executable:

$ chmod +x deploy/initiate.sh

work.sh does not need to be executable because it is never executed on your local computer.

Wrapping up

Add these files to your Git repository, commit and test the the script:

$ git add deploy/work.sh deploy/initiate.sh
$ git commit -m "Add deployment automation scripts"
$ ./deploy/initiate.sh

Congratulations, you are done automating redeployments.