Monday, January 29, 2007

Multiple Ruby on Rails apps with Mongrel and Apache

This post will show how to deploy multiple Ruby on Rails applications using Apache2.2 and Mongrel Clusters. The goal is to serve many apps under the same domain, for example:

http://www.domain.com/app1
http://www.domain.com/app2


The topic was discussed on the Mongrel mailing list (http://rubyforge.org/pipermail/mongrel-users/2006-September/001498.html), but even after reading it over and over for a few days, I could not make any of the suggestions there work, hence this post of what I did to make it work.

Preparation: Get 1 Ruby on Rails app deployed first! For the instructions on getting a single Ruby on Rails app running using Apache2.2, Capistrano and Mongrel, check out these excellent tutorials. I use the configuration file layout suggested by the codahale blog.

http://mongrel.rubyforge.org/docs/apache.html
http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/

Once you have a single app deployed and working properly, it is relatively easy to get the second one running under your domain - if you know what to do. You will configure and deploy your second app exactly the same way you did the first, with one exception. For both apps, you need to change the mongrel configuration to use the --prefix argument, besides that it is only 2 changes to your apache configuration. Here are the steps in detail:

Step 1) Use the --prefix flag of the mongrel configuration, here are 2 example mongrel_cluster.yml files.

---
prefix: /app1
cwd: /var/www/rails/app1/current
port: "8000"
environment: production
address: 127.0.0.1
pid_file: log/mongrel.pid
servers: 2

----------------------------------------------------------------------------------
---
prefix: /app2
cwd: /var/www/rails/app2/current
port: "8010"
environment: production
address: 127.0.0.1
pid_file: log/mongrel.pid
servers: 2


Step 2) Modify your RewriteRules in ds.common to redirect to the appropriate app. Here is what I have in my ds.common for serving dynamic content.

# Redirect all non-static requests to the right cluster
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^/app1(.*)$ balancer://app1%{REQUEST_URI} [P,QSA,L]
RewriteRule ^/app2(.*)$ balancer://app2%{REQUEST_URI} [P,QSA,L]


Step 3) Add a new cluster to proxy_cluster.com.
<Proxy balancer://app1 >
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
</Proxy >

<Proxy balancer://app2 >
BalancerMember http://127.0.0.1:8010
BalancerMember http://127.0.0.1:8011
</Proxy >