Ubuntu Intrepid - Nginx, rails and thin

Having installed the thin web server for Ruby, we can now look at configuring an Nginx vhost to proxy to thin so we can serve our Ruby on Rails application.

The process is easy to follow and easy to repeat for hosting multiple domains.


Setup

First, you need to have followed the previous Nginx articles, having installed Nginx via aptitude or via source.

You will also need to have installed the thin web server — see the article linked above.

Plan

The plan is very simple:

We'll create a basic rails application and use 3 thin instances running from port 3000 to 3002.

I won't go into detail as the thin web server for Ruby article shows how to install and configure thin.

Once that is done, we'll create a simple vhost to proxy requests to the thin instances.

You may also notice this article is very similar to the Nginx and mongrels article. There is a very good reason for that — they use exactly the same methods in creating the virtual host.

All the virtual host has to do is proxy requests to the 3rd party web server — in this case thin, in the sister article, mongrels.

Rails Application

To create a rail application, move into your public_html folder:

cd /home/demo/public_html

and create a new Ruby on Rails application:

rails railsapp

Done.

Thin

Ensure you are in the rails folder:

cd ~/public_html/railsapp

Then create a thin configuration file:

sudo thin config -C /etc/thin/railsapp.yml -c /home/demo/public_html/railsapp/  --servers 3 -e production

It's always a good idea to check the created file:

cat /etc/thin/railsapp.yml

The contents are as such:

--- 
pid: tmp/pids/thin.pid
address: 0.0.0.0
timeout: 30
port: 3000
log: log/thin.log
max_conns: 1024
require: []

environment: production
max_persistent_conns: 512
servers: 3
daemonize: true
chdir: /home/demo/public_html/railsapp

Unlike working with mongrels, with thin we don't need to manually create symlinks, etc. to make sure it's started after a reboot.

Now all we need to do is start thin:

sudo /etc/init.d/thin start

Done.

Nginx Virtual Host

Let's create the Nginx vhost:

sudo nano /etc/nginx/sites-available/domain.com

Note: If you installed Nginx from source, the path may vary to something like:

sudo nano /usr/local/nginx/sites-available/domain.com

The contents of the file are as such:

upstream domain1 {
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
        server 127.0.0.1:3002;
    }

server {
            listen   80;
            server_name  www.domain.com;
            rewrite ^/(.*) http://domain.com/$1 permanent;
           }


server {
            listen   80;
            server_name domain.com;

            access_log /home/demo/public_html/railsapp/log/access.log;
            error_log /home/demo/public_html/railsapp/log/error.log;

            root   /home/demo/public_html/railsapp/public/;
            index  index.html;

            location / {
                          proxy_set_header  X-Real-IP  $remote_addr;
                          proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_set_header Host $http_host;
                          proxy_redirect false;

                          if (-f $request_filename/index.html) {
                                           rewrite (.*) $1/index.html break;
                          }

                          if (-f $request_filename.html) {
                                           rewrite (.*) $1.html break;
                          }

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

}

Take it section by section and you will see that the basics are the same as for a 'normal' Nginx vhost.

We have the server_name, listen, log and index variables.

Where it differs is the addition of the Rails proxy settings.

In this example, we will use 3 thin instances running on ports 3000, 3001 and 3002 which I have defined in the 'upstream' setting. I've called it domain1 for ease of use.

The location settings say that if the requested file exists to serve the static version straight away.

And if the requested file doesn't exist, pass the request to the thin server.

Enable

Remember that we need to 'enable' any available vhosts or it won't be served (an easy thing to leave out).

Referring to the Nginx articles, all we need to do is create a simple symlink:

sudo ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/domain.com

Or, if you installed Nginx from source:

sudo ln -s /usr/local/nginx/sites-available/domain.com /usr/local/nginx/sites-enabled/domain.com

Done.

Restart

Final step is to restart Nginx:

sudo /etc/init.d/nginx stop
...
sudo /etc/init.d/nginx start

Use the 'stop' and 'start' method as issuing a restart command does not always work with Nginx.

Navigate

All that's left is to navigate to your domain:

http://www.domain.com

Where you will be greeted with the rails welcome page.

Summary

Setting up an Nginx virtual host to proxy to a thin server cluster is easy.

To serve multiple domains, simply repeat the process with the new domain details.

Mike

Article Comments:

florida web design commented Thu Apr 09 16:44:58 UTC 2009:

NgniX for anyone out there who hasn't tried it, is amazing. It's easier than pie to configure, runs amazingly fast for static / proxying purposes, and uses very little memory.

David Southard commented Thu May 14 22:06:35 UTC 2009:

FYI for those that are just deploying this in a barebones local situation. (i.e. no real DNS setup)

This line might trip you up.

server { listen 80; server_name www.domain.com; rewrite ^/(.*) http://domain.com/$1 permanent; }

Its a DNS redirect or alias for if someone puts www.domain.com into their browser instead of domain.com. It tripped me up that's why I put this here.

Van Miranda commented Thu Oct 29 21:37:30 UTC 2009:

This is a great article - it was the missing link I needed to get nginx/thin to host my Rails app. thank you!

If anyone gets the infinite redirect error after implementing this, it may mean that you have a minor typo (I did). Check your domain for each "server" block again and make sure "www." isn't present before your domain in both blocks.

Pawel Barcik commented Tue Dec 01 14:41:00 UTC 2009:

Nginx 0.7.64 is complaining about this line:

proxy_redirect false;

it suppose to be:

proxy_redirect off;

James Black commented Sun Jun 20 02:26:44 UTC 2010:

The configuration used above will redirect www.domain.com to domain.com, if this is not what you want, then you can delete the first server section and add www.domain.com to the server_name in the second server section.

Example:

server_name domain.com www.domain.com;

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)