Running NodeJS and Apache Side-by-Side on Ubuntu

I was setting up a server as a sandbox to run some of my personal projects. I needed the server to run PHP, Ruby, and Node.js applications. Running PHP and Ruby side-by-side on Apache is no problem. But running Node.js and Apache on the same box is an issue since Apache and Node.js need to listen for incoming requests on port 80.

The obvious solution is to use Apache as a proxy, passing along requests on port 80 for Node.js applications to their respetctive Node.js process. All other requests could be handled by Apache. This not ideal however, as it negates some of the performance benefits of using Node.js in the first place if we have to pass requests through Apache first.

It was clear to me that the best option would be write a proxy in Node.js and expose this process to the Internet by having it listen on port 80. I could then pass requests through to any aribtrary process quite easily using the node-http-proxy module.

Here is the script I created. If you use this, replace the obvious placeholder stuff with the appropriate values. You’ll also need to npm install http-proxy in your project folder as it is a dependency of this script.

// /var/www/proxy-server/proxy.js
var http = require(‘http’)
  , httpProxy = require(‘http-proxy’);

var options = {
  hostnameOnly: true,
  router: {
    ‘some-lamp-app.com’: ‘127.0.0.1:8080’,
    ‘some-node-app.com’: ‘127.0.0.1:3001’
  }
};

var proxyServer = httpProxy.createServer(options);
proxyServer.listen(3000);

So you may notice a couple seemingly strange things about the ports in this script:

  1. I have the proxy script listening on port 3000 instead of port 80. This is because root privileges are required to listen on port 80. Since I don’t want to escalate priveleges to run this script, I’ve set the script to listen on port 3000. A consequence of this is that I had to set-up the IP tables to forward all requests on port 80 to port 3000.
  2. I have a LAMP app listening on port 8080 instead of port 80. Apache listens on port 80 by default, but requests on port 80 are being forwarded to port 3000. As such, Apache needs to be configured to listen to another port. Port 8080 is as good as any.
  3. I have a Node.js app listening on port 3001. The Node.js app needs to listen on some port. I’ve decided to reserve port 3000-3999 for my Node.js processes.

Finally, you need to run the proxy script. Be aware that this is a long running process that you need to keep alive. I’m running this script on a Ubuntu 12.04 LTS server and chose to create an upstart service to manage the process. Monit and Forever.js are popular ways of doing this too.

Here’s my service which I created at /etc/init/proxyjs.conf. If you use this, replace the obvious placeholder stuff with the appropriate values.

#/etc/init/proxyjs.conf
description “Proxy written in Node.js”
author “Your Name”

start on (local-filestyles and net-device-up IFACE=eth0)
stop on shutdown

respawn

script
  cd /var/www/proxy-server/proxy.js
  exec /path-to/node proxy.js 2>&1 >> /var/log/proxyjs.log
end script

Note that the full path the Node binary needs to be used in the script. An easy way to find the path is to issue the command which node.

And that’s all there is to it. The service can be started with sudo start proxyjs; stopped with sudo stop proxyjs and restarted with sudo restart proxyjs. When the server is restarted the process will automatically spawn. Should the process crash it also be automatically respawned.