Thursday, December 09, 2010

Having fun with NodeJS

This is rather a memo for myself than tutorial of building a simple Web site using server-side JavaScript (read why you may need this).

I have registered a domain name, and purchased a 'Level 1' VPS hosting from HostGator (with pre-installed CentOS 5.5), but you can try this on a virtual machine running on your desktop as well.

1. Let's start from installing node.js:

# Download the source package:

# Build & Install:
tar -zxf node-v0.2.5.tar.gz
cd node-v0.2.5
sudo make install

2. Now, we need to install a package manager for node.js:

# It's recommended to run npm from a regular user, so we just make the /usr/local/ directory writable by the group 'wheel', and add the relevant user to this group:

sudo chgrp -R wheel /usr/local/{share/man,bin,lib/node}
sudo usermod -g -G wheel $USER

# Install npm:
curl | sh

3. As developer of node.js himself states, node.js isn't production ready yet. What he suggests is running node.js behind a reverse proxy, served by nginx, for example.

a) Installing nginx is very easy on CentOS:

# Add EPEL repository:
rpm -i

# Install 'nginx':
yum install nginx

b) Let's configure nginx proxy:

# First, comment out the server {...} section in /etc/nginx/nginx.conf:

vim /etc/nginx/nginx.conf

# Second, add the proxy configuration to /etc/nginx/conf.d/virtual.conf (we suppose that your node.js application will be running on port 8000):

cat <<EOF >> /etc/nginx/conf.d/virtual.conf
upstream app_cluster_1 {

server {
        server_name node.local node;
        access_log /var/log/nginx/node.log;

        location / {
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_set_header X-NginX-Proxy true;

          proxy_pass http://app_cluster_1/;
          proxy_redirect off;

4. Create your simple Web application:

a) We will use ExpressJS as a Web framework, so we need to install it first:

npm install express

b) Let's install templates engine as well. I've tried to use Haml template engine, but I couldn't make it render pages properly, so I was forced to move to using ejs (and I don't regret that):

npm install ejs

c) Create the application folders:

mkdir /var/www/apps/your_app

# Static content will be placed here:
mkdir /var/www/apps/your_app/static

# Views (templates) folder:
mkdir /var/www/apps/your_app/views

Here are files that we are going to create under these folders:


var sys = require('sys');
var express = require('express');
var app = express.createServer();

        app.use(express.staticProvider(__dirname + '/static'));
        app.set('views', __dirname + '/views');
        //app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

var site_locals = {
        copyright: 'Copyright @ Michael Spector 2010',

app.get('/', function(req, res){
        res.render('hello.ejs', {
                locals: { site: site_locals },



                <title>My App</title>
                <link rel="stylesheet" href="/style.css" />
              <!-- Pay an attention to this special construct that will be replaced with the actual view contents (hello.ejs in our case): -->
              <%- body %>
              <%= site.copyright %>


<h1>Hello, World!<h1/>


body {
   text-align: center;

5. The last this is making sure that if node.js unexpectedly dies, it will be started again automatically. For this purpose we will install monit:

# Install monit:
yum install monit

# Uncomment "set httpd" entires in the main configuration file:
vim /etc/monit.conf

# Create the configuration file for your application (note that we define NODE_ENV=production variable prior running node.js, which should enable all production features, like caching, etc...):

cat <<EOF > /etc/monit.d/your_app
check host objdump with address
    start program = "/bin/sh -c 'NODE_ENV=production /usr/local/bin/node /var/www/apps/your_app/app.js'"
        as uid nobody and gid nobody
    stop program  = "/usr/bin/pkill -f 'node /var/www/apps/your_app/app.js'"
    if failed port 8000 protocol HTTP
        request /
        with timeout 10 seconds
        then restart

6. Finally, configure all services to start automatically when system boots, and start them:

sudo chkconfig nginx on
sudo chkconfig monit on

/etc/init.d/nginx restart
/etc/init.d/monit restart

monit stop your_app
monit start your_app

If you need to restart your application upon re-deployment, run:

monit restart your_app

Go to http://<your-ip>/, and have fun!

Hope this tutorial helps you.


James said...

Pretty in depth. Thanks!

Seva (Wsevolod) Lapsha said...


soj said...

node.js spreading its wings !!!

Ajay Verma said...

Node.js gives developers the opportunity to work in non-blocking, event-driven environment. With Node.js, real-time web applications can use a 2-way communication paradigm and can push data to the client.