Saturday, April 21, 2007

Apache 2.2.4 and Mongrel on Ubuntu

This second installment about installation of the new Apache 2.2.4 and it's configuration for production use with Ruby on Rails and Java. This installment discusses installation of Mongrel and it builds on installation of apache.

Mongrel Installation

Install mongrel and its supporting software. Make sure when prompted you select the most recent, non mswin32 option.

sudo gem install daemons gem_plugin mongrel mongrel_cluster --include-dependencies

Set up mongrel cluster

When deploying a mongrel cluster, none of the mongrel servers will be listening on a privileged port. This means that you don't have to run mongrel as root. I usually use just my normal non-root user to run the mongrel cluster. It also helps to avoid problems with file permissions.

For the purpose of this example we will just use a freshly minted rails app. You can adjust these instructions to work with your app, wherever you may have placed it. I usually put all the applications in /home/peter/rails/. So lets go set up our app and test that mongrel will serve it:

mkdir -p /home/peter/rails/mediacom/releases/
cd /home/peter/rails/mediacom/releases/
rails 1
cd ../
ln -s current releases/1
cd current
mongrel_rails start

You should now be able to see your application at http://host:3000/. If you can, you are good to go. Hit CTRL+C to stop the mongrel server. At a minimum the log directory of your app has to be writable by the peter user:

sudo chown -R peter:peter /home/peter/rails/mediacom/

With mongrel working and our webapp directory prepared we can proceed with the mongrel_cluster configuration step:

sudo mongrel_rails cluster::configure -e production \
   -p 8000 -N 3 -c /home/peter/rails/mediacom/current -a \
   --user peter --group peter

This will write a configuration file in config/mongrel_cluster.yml. We have setup to run our cluster in production mode as the user mongrel and will start 3 mongrel servers listening on ports 8000, 8001, and 8002. Now, lets do a quick test of what we have setup so far:

sudo mongrel_rails cluster::start

Checking our host on ports 8000, 8001, and 8002 we should now be able to see our test application. We can stop all of those mongrels with

sudo mongrel_rails cluster::stop.

On Boot Initialization Setup

At this point, mongrel and mongrel_cluster are setup and working with our sample webapp. Ultimately, we want this cluster to start on boot. Fortunately, mongrel_cluster comes with an init script that we can just drop into place. All we need to do is put the configuration files in /etc/mongrel_cluster and take care of a few system tasks:

sudo mkdir /etc/mongrel_cluster
sudo ln -s /home/peter/rails/mediacom/current/config/mongrel_cluster.yml \

The following step needs to be done only once and ofcourse you mongrel_cluster version may vary:

sudo cp \
   /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/resources/mongrel_cluster \
sudo chmod +x /etc/init.d/mongrel_cluster

Now we have a typical System V init script that will launch our mongrel cluster. Actually, this script will launch any cluster that has a configuration file in /etc/mongrel_cluster/. So when we run /etc/init.d/mongrel_cluster start it will start all clusters. Likewise for stop and restart. To install the script use:

sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults

Change the shebang line (the first line) of the mongrel_cluster_ctl to:

#!/usr/local/bin ruby

Apache configuration

Probably the most difficult part. As the apache was compiled from source the configuration files are located quite nonstandardly under /usr/local/apache/conf. As I use the apache for hosting multiple applications (I really wonder how many mongrel instances can such slice host sustain :-) I create a separate folder for configuration files for each of them. This example uses mediacom application and will be accessible from virtual domain Of course when setting up another application instead of mediacom in files and folder names use the appropriate name :-)

1) Create folder for configuration files

mkdir /usr/local/apache/conf/mediacom.conf
cd /usr/local/apache/conf/mediacom.conf

2) Create file mediacom.common

 DocumentRoot /home/peter/rails/mediacom/current/public

   Options FollowSymLinks
   AllowOverride None
   Order allow,deny
   Allow from all

 RewriteEngine On

 # Uncomment for rewrite debugging
 #RewriteLog logs/myapp_rewrite_log
 #RewriteLogLevel 9

 # Check for maintenance file and redirect all requests
 #  ( this is for use with Capistrano's disable_web task )
 RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
 RewriteCond %{SCRIPT_FILENAME} !maintenance.html
 RewriteRule ^.*$ /system/maintenance.html [L]

 # 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
 RewriteRule ^/(.*)$ balancer://mongrel_cluster_mediacom%{REQUEST_URI} [P,QSA,L]

 # Deflate
 AddOutputFilterByType DEFLATE text/html text/plain text/css
 # ... text/xml application/xml application/xhtml+xml text/javascript
 BrowserMatch ^Mozilla/4 gzip-only-text/html
 BrowserMatch ^Mozilla/4.0[678] no-gzip
 BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

 # Uncomment for deflate debugging
 #DeflateFilterNote Input input_info
 #DeflateFilterNote Output output_info
 #DeflateFilterNote Ratio ratio_info
 #LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
 #CustomLog logs/myapp_deflate_log deflate

3) Create mediacom.conf

    Include conf/mediacom.conf/mediacom.common

 # This is required to convince Rails (via mod_proxy_balancer) that we're
 # actually using HTTPS.
 RequestHeader set X_FORWARDED_PROTO 'https'

   ErrorLog logs/mediacom_errors_log
   CustomLog logs/mediacom_log combined

4) Create mediacom.proxy_cluster.conf

Note; Of course the port numbers will differ (based on whatever you configured when setting up mongrel cluster.

5) Create mediacom.proxy_frontend.conf

Listen 8100

   SetHandler balancer-manager
   Deny from all
   Allow from
Of course the port number will have to be unique on the server. Allow access from your current location (or whatever the location you will need the access from)

6) Inform httpd.conf about your configuration files At the following to the very bottom of /usr/local/apache/conf/httpd.conf

Include conf/mediacom.conf/*

7) Restart apache and you should be good to go. Of course, you will have to make sure that the virtual host subdomain actually points to the server (i.e. that will actually point to your server - for testing just make an entry in /etc/hosts)

/usr/local/apache/bin/apachectl stop
/usr/local/apache/bin/apachectl start

8) Go to and you should be able to see your app :-)

No comments:

Post a Comment