Ubuntu Hardy - 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 mongrel clusters.
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):
cwd: /home/demo/public_html/railsapp
log_file: log/mongrel.log
port: "5000"
environment: production
address: 127.0.0.1
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 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.
PickledOnion


Article Comments:
John Topley commented Thu Aug 07 17:32:25 UTC 2008 ago:
I'm guessing that this config doesn't use Nginx to serve static assets such as images i.e. everything goes through Rails?
Puzzled commented Sat Aug 09 20:52:16 UTC 2008 ago:
Great article.
I've gotten proxying to work. The problem is that static content is served much slower through nginx than through mongrel directly.
For example:
http://example.com/static_file.jpg
is served at <10K/s. But:
http://example.com:3000/static_file.jpg
is served at 400+ K/s.
I can stop the mongrel process and still download the file at:
http://example.com/static_file.jpg
but the transfer rate is still < 10K/s.
(note to John, yes, I had to set up the config file to handle images separately, apparently).
Sujay commented Sun Aug 24 07:24:28 UTC 2008 ago:
Hi,
I could run this for http://llet.in .. but I want to create a sub-domain .. bu .. so that my site becomes http://bu.llet.in .. how can I do that?
davos commented Sun Sep 07 03:00:56 UTC 2008 ago:
Great article - you got me up & running in no time.
thanks!!