Ubuntu Intrepid - Nginx, rails and mongrels

Following from the mongrel and mongrel cluster article, we can now look at configuring Nginx to proxy to a mongrel cluster so we can serve our Ruby on Rails application.

The process is very easy and can simply be repeated for serving multiple domains.


Setup

Firstly you will have needed to follow the previous Nginx articles and installed via aptitude or via source.

You will also need to have installed mongrels as per the article linked to above.

Plan

The plan is very simple:

We'll create a basic rails application and use 3 mongrels running from port 5000 to 5002.

Beyond creating the cluster itself, I won't go into detail as the mongrel and mongrel cluster article shows how to install and create a mongrel cluster.

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

Simple as that.

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.

Mongrel Cluster

Ensure you are in the rails folder:

cd ~/public_html/railsapp

Then create a mongrel cluster file as such:

mongrel_rails cluster::configure -e production -p 5000 -N 3 -c /home/demo/public_html/railsapp -a 127.0.0.1

It's always a good idea to check the created file (config/mongrel_cluster.yml):

--- 
address: 127.0.0.1
log_file: log/mongrel.log
port: "5000"
cwd: /home/demo/public_html/railsapp
environment: production
pid_file: tmp/pids/mongrel.pid
servers: 3

Now create a symlink to the /etc/mongrel_cluster folder (this ensures the cluster is restarted on a reboot):

sudo ln -s /home/demo/public_html/railsapp/config/mongrel_cluster.yml /etc/mongrel_cluster/railsapp.yml

Now all we need to do is start the cluster:

mongrel_cluster_ctl 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:5000;
        server 127.0.0.1:5001;
        server 127.0.0.1:5002;
    }

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 each section at a time 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 mongrels running on ports 5000, 5001 and 5002 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 straightaway.

If the requested file doesn't exist, pass the request on to the mongrels. In this case it would proxy to 127.0.0.1:5000, 5001 and 5002 as those are the ports we defined at the beginning of the file.

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 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 Nginx virtual hosts to proxy to a mongrel cluster is fairly simple.

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

Mike

Article Comments:

socrateos commented Mon Aug 08 00:24:36 UTC 2011:

Is it supposed to be upstream domain { and not upstream domain1 { ?

Jered commented Mon Aug 08 20:28:45 UTC 2011:

The "domain1" is a label, so it can actually be anything you like for that "upstream" directive. You can use different labels if you're defining more than one upstream entry for virtual hosts.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)