Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js setup for easy deployment and updating

We're currently developing a website (TYPO3 under Apache) for a customer that is supported by a node.js/socket.io application that provides realtime updates to the content served from the CMS.

As this is our first node.js project I don't have any best practices to go by when it comes to 'the perfect setup' so I've spent some time researching deployment techniques.

A couple of questions remain for me to achieve a good setup which:

  1. Is easy for the customer to deploy. This is very important because our website will be integrated in their 'live' TYPO3 installation which serves an abundance of websites and is running on servers which aren't managed by the customer but another (centralized) organization which makes support calls and server changes a slow process.

  2. Should be easy to update. As mentioned requesting restarts and making server changes is a slow process, so idealy the node installation should restart / update when it receives changes that are pushed onto the live installion using git.

Deployment

The general consensus seems to be to use forever when it comes to deploying node applications to keep them running. I've tested forever, and it seems to work fine when installed by npm install forever -g (global). This would require external assistance to globally install on the live environment though, so I'd prefer to have it running from the application's node_modules directory, but I haven't been able to create a solid wrapper to do so.

Additionally, forever works fine, but it has to be started manually. What would be the best approach to ensure that it gets started on server boot and keeps running?

  • A simple init.d script?
  • Writing a watchdog wrapper?
  • A TYPO3 scheduler task that checks forever status?

Rapid development / Restart on update

We're currently still in the development stage of the project and every time I make changes to the node.js application I manually restart node or forever. This works, but is far from ideal. There are several smaller npm modules that check for file modifications and restart node upon detected changes, like:

  • Nodemon
  • Node.js Supervisor
  • Bounce
  • Nodules (which doesn't require restarting node, so might be easier to combine with forever)
  • Up

Does anyone have experience with any of these?

Update: Why don't you just use Cluster?

The Cluster module provides similar functionality through the reload mechanism, but doesn't work with Node 0.5+. The core Cluster module (Node 0.6+) that replaced it doesn't have all these features but only provides clustering. Which in turn doesn't play well with socket.io. At least not without using Redis (which is a problem for us, because we can't force another prereq service to the customer).

--

Obviously I'm trying to find the most stable solution that combines an update-restarter with forever before handing over the project to the customer and I'm really hoping anyone has produced a proven combination of techniques.

like image 607
Rem.co Avatar asked Jun 18 '12 13:06

Rem.co


People also ask

How much RAM is required for NodeJS?

256 MB is sufficient amount of RAM to run Node. js (e.g. on Linux VPS instance), assuming no other memory-hog software is run.


2 Answers

Combining all knowledge gathered (Big thanks to Julian Knight for the ideas) and methods tested in the past week, I've decided to settle for the deployment solution described below (I thought I'd be nice to share to help others with comparable questions):

Auto-restarting on script errors and automatic reloading on script changes is handled by forever, as it also includes a script watch, as long as Forever is spawned from within a node.js script.

To do so, I've added a server.js to launch the app.js script we actually want to run:

server.js

var forever = require('forever'),     child = new(forever.Monitor)('app.js', {         'silent': false,         'pidFile': 'pids/app.pid',         'watch': true,         'watchDirectory': '.',      // Top-level directory to watch from.         'watchIgnoreDotFiles': true, // whether to ignore dot files         'watchIgnorePatterns': [], // array of glob patterns to ignore, merged with contents of watchDirectory + '/.foreverignore' file         'logFile': 'logs/forever.log', // Path to log output from forever process (when daemonized)         'outFile': 'logs/forever.out', // Path to log output from child stdout         'errFile': 'logs/forever.err'     }); child.start(); forever.startServer(child); 

This watches all files in the application directory for changes and restarts the script running in foreveras soon as one changes. Because the logs and pidfile are in subdirectories of the application, those have to be ignored from the file watch, or the script will loop restarts:

.foreverignore

pids/** logs/** 

To make this all start on system boot and enabling us to easily control the service using start node-appand stop node-app we use Ubuntu's Upstart. I've combined two examples (this and this one) into one that does the job quite well:

/etc/init/node-app.conf

# This is an upstart (http://upstart.ubuntu.com/) script # to run the node.js server on system boot and make it # manageable with commands such as # 'start node-app' and 'stop node-app' # # This script is to be placed in /etc/init to work with upstart. # # Internally the 'initctl' command is used to manage: # initctl help # initctl status node-app # initctl reload node-app # initctl start node-app  description "node.js forever server for node-app" author      "Remco Overdijk <[email protected]>" version "1.0"  expect fork  # used to be: start on startup # until we found some mounts weren't ready yet while booting:  start on started mountall stop on shutdown  # Automatically Respawn: respawn respawn limit 99 5  env HOME=/home/user/node-app-dir  script     # Not sure why $HOME is needed, but we found that it is:     export HOME=$HOME     chdir $HOME     exec /usr/local/bin/node server.js > logs/node.log & end script  #post-start script #   # Optionally put a script here that will notifiy you node has (re)started #   # /root/bin/hoptoad.sh "node.js has started!" #end script 

As Kevin wisely mentions in his article it's unwise to run node as root, so we'll change that to exec sudo -u www-data /usr/local/bin/node when we move to new servers next week.

So, forever gets started automatically by node server.js which gets launched by upstart, and monitors for crashes and file changes, keeping the entire setup running as long as we want.

I hope this helps anyone.

like image 184
Rem.co Avatar answered Sep 22 '22 08:09

Rem.co


Since my last answer is for the future! Here are some other links to assist:

  • https://serverfault.com/questions/274857/how-to-use-node-js-as-a-production-web-server
  • http://www.slideshare.net/the_undefined/nodejs-best-practices-10428790 (see slide 35)
  • http://www.slideshare.net/the_undefined/nodejs-in-production (slides 31 to the end)
  • When node.js goes down, how can I bring it back up automatically?

There doesn't yet seem to be a perfect answer but there are plenty of people running production Node instances. Hopefully this will point you in the right direction.

like image 40
Julian Knight Avatar answered Sep 20 '22 08:09

Julian Knight