Upstart and Node.js

One issue that we have had with Node.js projects is how to allow our developers to assume the role of devops for the various different sites a machine may be running - i.e. to restart node sites without incurring a large overhead in server configuration.

To date we have been running our node sites out of the Upstart system in Ubuntu Linux, and are using one upstart script per site.  With a server running several sites, this would translate to a lot of these scripts, all pretty much identical apart from some variables.

My solution to this is as follows....

First of all, there are a few dependencies to mention.

  • The first is that we are dependent on Upstart.  Other than Ubuntu, there are a few recent distributions that also use the system.  Redhat Enterprise 6 and Fedora 6 are listed as supporting it on the wikipedia page for Upstart.
  • The next is of course Node.js.  This method could however be transferable to other services that run lots of individual instances.
  • Lastly, we need a way of maintaining the right version of node for each instance, and we use n (npm install -g n) for this purpose.

The solution comes in two parts.  One upstart script to start each node instance, the second to start them all on boot.

 

Part One: node.conf

description 'node upstart script'
author 'iain'

start on (local-filesystems and net-device-up)
stop on shutdown

instance "Node - $NAME"

respawn
respawn limit 5 60

script
        . /etc/node/$NAME.conf
        exec sudo -u node NODE_ENV=${NODE_ENV} /usr/bin/n use ${NODE_VERSION} ${NODE_PATH} >> ${LOG_PATH} 2>&1
end script
The key to running multiple instances is in the 'instance' keyword above, and we pass in the NAME variable on the command line to specify which instance we are operating on. Another thing that you'll notice is that we are sourcing a configuration file, this is so that we can populate the rest of the script with variables, so the next step is to create this directory and set the variables for one application. For my test node app, I've very creatively called it test, and have decided it's running in a production environment.  Therefore my config file is /etc/node/test-production.conf and contains:
NODE_VERSION="0.6.5"
NODE_PATH="/var/application/test/app.js"
LOG_PATH="/var/log/node/test.log"
NODE_ENV="production"
Starting this node instance is easy, we run:
# start node NAME=test-production
And as output we get:
# start node NAME=test-production
node (Node - test-production) start/running, process 1562
All is good, we can stop/start/restart/respawn this service, but it won't start automagically on boot.  For this we need....   Part Two: nodeSites.conf
description 'Start all node instances at boot'
author 'iain'

start on (local-filesystems and net-device-up)

task

script
  for file in `ls /etc/node/*.conf` ; do
    filename=`basename ${file%.*}`
    start node NAME=$filename
  done
end script

As you can see, this script will cycle through all config files in /etc/node and start a node instance for each based on the name of the file (minus path and extension for those unfamiliar with the `basename ${file%.*}` line).

The key thing to mention about this script is the task keyword.  It is this that makes this upstart script a short lived process - it does its thing then dies off.

 

More information on the technologies mentioned can be found at....

NodeJS - http://nodejs.org

NPM module n by TJ Holowaychuk - http://github.com/visionmedia/n

Upstart Cookbook - http://upstart.ubuntu.com/cookbook

Ubuntu - http://ubuntu.com

Bash Manual - http://www.gnu.org/software/bash/manual/bashref.html

 

Content on this blog is licensed under a Creative Commons Attribution 3.0 License.

Join Us

Come and work for Clock

Clock is made up of bright, hard-working and talented people and we're always on the look out for more. You can browse the current jobs below or follow us @clock for the latest vacancies.

View
Jobs