How to run Apache and NodeJS based sites on the same server with Varnish

April 15, 2012 – 7:11 pm Tags: , , , ,

While developing Battlefield 3 Web Commander, I wanted to keep it on my VPS where I was already running Apache.

Of course I had the option of putting it in a non-standard port like 8080, but it wouldn’t be nice if the URL would be somedomain.com:8080. The second option was ordering an extra IP address from Linode. That would’ve cost me a bit each month, so I didn’t really want to do that either.

The third option turned out to be pretty easy: Use Varnish.

Here’s how I did it…

Step 1: Put your servers on non-80 ports

First, we need to put Apache on some other port than 80. Simply change the Listen option in Apache’s config.

Let’s say Apache goes to port 6001 for this example.

The node application will also need to run on some other port than 80. Let’s put it to port 6002.

Step 2: Configure Varnish on port 80

First, find your Varnish config file. On Ubuntu, you can probably find it at /etc/default/varnish

Find the DAEMON_OPTS

Make sure the DAEMON_OPTS uses port 80 in the -a flag as follows:

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

Or, if you use the advanced configuration, set VARNISH_LISTEN_PORT to 80.

Step 3: Set up Varnish proxying to Apache and Node

Open your varnish VCL file, most likely it is /etc/varnish/default.vcl

You will need to set up backends for all your servers here. In my case, I will set up backends “apache” and “node”, as follows:

backend apache {
    .host = "127.0.0.1";
    .port = "6001";
}

backend node {
    .host = "127.0.0.1";
    .port = "6002";
}

Next, we need to define the vcl_recv sub to route between these backends. This goes after the backend definitions in the VCL file:

sub vcl_recv {
    if(req.http.host == "apachesite.com") {
        set req.backend = apache;
    }

    if(req.http.host == "nodesite.com") {
        set req.backend = node;
    }
}

All we need to do is check what the host in the request is: If the domain used is apachesite.com, the request will be proxied to Apache, and for nodesite.com, to Node.

If you want to use a single domain, you could use subdomains to check which backend to use as well. In my case, I have an additional subdomain which I use to access my development node instance.

Step 4

There is no Step 4.

Conclusion

By using Varnish on port 80, we can pretty easily have any number of other servers serving content so that it seems that all of it is on port 80 when it really isn’t.

This of course is not the only thing Varnish can do. You can set up caching and all sorts of stuff to it, but for that you probably should look at the Varnish manual

Share this:

RSS feed Subscribe to my RSS feed

  1. 4 Responses to “How to run Apache and NodeJS based sites on the same server with Varnish”

  2. Thanks for the tip Jani.

    How does your solution perform with websockets ? Are they correctly passed through Varnish ?

    By Delapouite on Apr 17, 2012

  3. Follow the instructions on the Socket.IO wiki which makes them work nicely https://github.com/LearnBoost/socket.io/wiki/Varnish-and-Socket.IO

    Be sure to have the same domain/port combo as well. I mistakenly had domain.com and for socket.io, domain.com:12345, which made it not work with WebSockets.

    By Jani Hartikainen on Apr 17, 2012

  4. You could also have just set up a reverse proxy with Apache, and it would have been easier than using Varnish.

    By reņģis on Apr 17, 2012

  5. Hi,

    I’ve a website built with PHP on Hostgator and I want to run node.js app on the background.

    What do you suggest? I tested my app on a local computer (Windows) which I installed node.js and WAMP and they work together very smoothly.

    I can’t figure out how to put it into a real world.

    On my local computer, I don’t need to set up anything. Just run them separately and they will each do their jobs.

    Thanks

    By ket on Aug 23, 2012

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)