NGINX + Node.js + Windows Azure

I recently did a talk showing how you can easily get a node.js server up and running in Azure, fronted by NGINX using my AzurePluginLibrary. Here’s how it works.

Motivation

This is really a demonstration of the plugin library, rather than the capabilities of Azure. Azure will run node.js using Websites and Cloud Services, using IISNode. However, there are a couple of scenarios where you might not want to use IISNode; 1) it adds an overhead, thus reducing the capacity of your server, 2) if you want node to act as a socket server – IIS currently doesn’t support raw sockets. Using a reverse HTTP proxy like NGINX is a fairly common, it’s quickly becoming one of the top web servers on the internet.  NGINX will handle things like SSL, GZIP compression, load balancing, URL rewriting and serving static content with some simple configuration.

1. Installing the plugins

Download APM, a command line tool for installing plugins, which extend the capability of the Azure SDK. Then run APM elevated, with these commands (it’s case sensitive):

> apm install Node
> apm install nginx

This will install the plugins for Node and NGINX in your Azure SDK plugins folder. You only need to do this once.

2. Create the worker role

In Visual Studio, create a new Cloud project, and add a Worker Role. Add a server.js file to the Worker Role project, which looks something like this:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(210);

Notice that the web server is started on port 210.

Set the properties of the server.js file to ‘Copy if newer’ to ensure it is included in the Azure package. The Node plugin will run a server.js file if it finds it in the e:\approot\ folder.

Now create a ‘conf’ folder in your worker role, and add an nginx.conf file to that directory. I used a file like this:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        location / {
           proxy_pass  http://localhost:210;
           proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        }
    }
}

This forwards requests from port 80 to port 210. It doesn’t do much else, but you can alter this configuration to include the features you want. This gist is a good example.

Set the properties of the nginx.conf file to ‘content’ and ‘copy if newer’. This will ensure the file is included in the package, with the sub-directory preserved. The nginx plugin will inspect the conf folder in e:\approot\ and use any configuration files placed there.

The last thing to do is to alter the ServiceDefinition.csdef file in your Cloud Project, to include the two plugins, and expose port 80. It should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzure1" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-05.1.7">
  <WorkerRole name="WorkerRole1" vmsize="Small">
    <Imports>
      <Import moduleName="nginx"/>
      <Import moduleName="Node"/>
    </Imports>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="tcp" port="80" localPort="80" />
    </Endpoints>
  </WorkerRole>
</ServiceDefinition>

3. Deploy Your Project

With any luck you’ll be able to browse to your *.cloudapp.net address, and see Hello World!

Advertisements