Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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.

share|improve this question
    
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 '12 at 1:37
add comment

1 Answer

up vote 6 down vote accepted

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.

share|improve this answer
    
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 '12 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 '12 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 '12 at 16:52
2  
this URL is blank, do you have a copy content? –  mikhailov Dec 29 '12 at 13:35
    
So how to serve static assets if they are on a different machine than nginx? –  RocketR Jun 26 at 10:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.