Ruby on Rails - Deployment with mongrel

Well, I have been running rails for a couple of years now on some lightly loaded sites. Meanwhile rails has moved on to 2.0 and beyond, and I am hearing that mongrel provides a solution that works with just an apache server. My current deployment runs a frontend apache server, but hands off the rails stuff via proxy to a lighttpd server running on some port other than port 80 (like 8080).

This worked fine for quite a while, but then along came Fedora Core 9. This in and of itself should not be a showstopper, but the rub was no lighttpd-1.4.18. The latest version of lighttpd (1.4.19) makes my rails configuration blow up, and my solution was to run 1.4.18 as long as possible, and now that era seems to have come to an end.

So, onward with mongrel. Most folks seem to be happy with apache and mongrel working together to run rails. I am looking for the bandwagon to jump on, since I have other things to give me headaches.

Get the packages

I already have apache (2.2.9) already chugging away, so that is not a problem. I am running apache 2.2.8 and my apache has the proxy_module and proxy_balancer_module. (This is discovered via apachectl -M and apachectl -v.

Getting mongrel offers choices (namely whether to get it via the ruby-gem facility or via yum). Yum offers rubygem-mongrel, so that is the logical (maybe?) first thing to try:

yum install rubygem-mongrel

I don't know what this did (I seems to sort of have installed mongrel 1.0.1), but I later discover that I am still missing mongrel_cluster, so I install it as follows:

gem install mongrel_cluster
This does not find mongrel, and goes on to install mongrel 1.1.5, which does sound better, but leaves me uncertain about where I stand with the yum package I installed previously. I was edgy about gem/yum conflicts and this confirms my worries, but on we go. It will be nice when there are fedora packages that make rails work easily out of the box, but apparently rails is much too cutting edge for the fedora crowd, and/or fedora developers aren't rails savvy.

I long ago got my rails stuff via yum as rubygem-rails (I have 2.1.1), activerecord (2.1.1), and so on. Via yum or gem? I can't remember.

Set up the rails application for mongrel

My application is called "micros".
cd /u1/rails/micros
mongrel_rails cluster::configure -N 2 -p 8000 -e production -a 127.0.0.1 -c /u1/rails/micros
cd /etc/mongrel_cluster
ln -s /u1/rails/micros/config/mongrel_cluster.yml micros.yml
Some online guides advise adding --user mongrel --group mongrel Notice that I name the link in /etc/mongrel_cluster to be micros.yml. This is because I anticipate having multiple applications (set up as virtual hosts) and this will keep them organized.

The net effect of this is to create /u1/rails/micros/config/mongrel_cluster.yml which looks like this:

--- 
cwd: /u1/rails/micros
log_file: /u1/rails/micros/log/mongrel.log
port: "8000"
environment: development
address: 127.0.0.1
pid_file: /u1/rails/micros/tmp/pids/mongrel.pid
servers: 2
The full path names for log_file and pid_file are from back when I was thrashing around because I had omitted the -c switch, and had no cwd line.

To test fly this, start the cluster via su ; service mongrel_cluster restart. You should be able to go to http://localhost:8000 and http://localhost:8001 and see your application running.

Setting up an apache proxy to the cluster

I only run two mongrel servers, because I anticipate this being a very low traffic site.

I finally got smart and put all the configuration for this virtual host into /etc/httpd/conf.d/micros.conf which looks like this:

<VirtualHost *:80>
    # -- micros --
    ServerName micros.fish.org
    ServerAlias micros
    DocumentRoot "/u1/rails/micros/public"
    ProxyRequests Off
    ProxyPreserveHost On
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPass / balancer://mongrel_cluster/
    ProxyPassReverse / balancer://mongrel_cluster/

    ErrorLog logs/micros-error_log
    CustomLog logs/micros-access_log common
    CustomLog logs/micros-referer_log referer
    CustomLog logs/micros-agent_log agent

    RewriteEngine On

    # Rewrite index to check for static
    RewriteRule ^/$ /index.html [QSA]

    # Rewrite to check for Rails cached page
    RewriteRule ^([^.]+)$ $1.html [QSA]

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

<Proxy balancer://micros>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
</Proxy>
Note the word micros in two places in the above config file to match the application name, in particular the RewriteRule than hooks to the balancer, and the Proxy balancer section itself.

Monitoring the mongrel cluster

I didn't do it, but you could add some lines like the following and get access to a page that would give cluster statistics:
Listen 8080
<&VirtualHost *:8080>
<&Location />
SetHandler balancer-manager
Deny from all
Allow from all
<&/Location>
<&/VirtualHost>

Some links

Take a look at these links (maybe ancient) to notes by people who are doing rails via mongrel. Apparently capistrano is some kind of high level package to make all this easier. Maybe I am missing out by not running it. Who knows? Too many learning curves all at once.
Feedback? Questions? Drop me a line!

Ruby on Rails notes / tom@mmto.org