3

I've got a pretty standard Rails application running with Unicorn and Nginx all on one box. I'd like to split off the application itself and have Nginx on one machine and Unicorn (with the Rails app) on another machine. The idea here being that I'd like to add another app server with Unicorn later in the future, mostly for some light load balancing.

I may be tackling this from the wrong angle. Is this normal/possible? If so, can someone point me to example configs or documentation?

If it's not the way to go, what's the proper route to achieve the end goal? I've looked into HAProxy, but after reading through some Nginx/Unicorn documentation, I get the idea that this can be achieved without any additional software.

1
  • Note that I may just be confused with documentation. I'm pretty sure there's got to be some sort of HAProxy like magic happening between the two.
    – cmhobbs
    Mar 21, 2012 at 1:37

1 Answer 1

7

This is normal. You don't need HAProxy, though HAProxy may provide you with "fairer" load balancing between the app servers than the nginx load balancing.

So, on your app servers, set Unicorn to listen a network interface. This should preferably be a private IP address. For this example, let's say your app servers are 192.168.1.100, 192.168.1.101 and 192.168.1.102. Configure unicorn to listen to port 8000 on all the app servers.

On the nginx side, you'll have an "upstream" block like:

upstream unicorn {
  server 192.168.1.100:8000;
  server 192.168.1.101:8000;
  server 192.168.1.102:8000;
}

Then you will have your virtual server definition with a block like:

location / {

    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X_FORWARDED_PROTO $scheme;
    proxy_set_header  Host $host;

    proxy_connect_timeout 3;
    proxy_read_timeout 60;
    proxy_send_timeout 60;

    proxy_redirect off;
    proxy_max_temp_file_size 0;

    if (!-f $request_filename) {
      proxy_pass http://unicorn;
    }
}

You may need other proxy statements to get things to work like you want, but that should essentially do it. The proxy_pass statement will use the block defined in the upstream block, and will distribute jobs to the listed app servers. Check nginx documentation on other options that might be appropriate.

5
  • How will this handle static assets? For example, images or files in the app's public directory? Will those need to be hosted upstream on the Nginx machine?
    – cmhobbs
    Mar 21, 2012 at 2:09
  • The "if" statement (actually, with current nginx versions, it'd be "try_files") will test if a file exists in the document root. If it does, nginx will serve it. If not, the request goes to the proxy. Check the current docs (this is an example from an older nginx) and look at the "try_files" directive: wiki.nginx.org/HttpCoreModule#try_files
    – cjc
    Mar 21, 2012 at 2:26
  • 1
    This actually worked really well. I tossed together a quick blog post detailing the process: altbit.org/2012/04/03/unicorn-and-nginx.html
    – cmhobbs
    Apr 3, 2012 at 16:52
  • 2
    this URL is blank, do you have a copy content?
    – Anatoly
    Dec 29, 2012 at 13:35
  • So how to serve static assets if they are on a different machine than nginx?
    – RocketR
    Jun 26, 2014 at 10:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .