mod_rails and mod_php: playing nice together

Phusion’s Passenger (aka mod_rails) is an excellent Apache plugin for serving Rails apps. But it can cause issues if you also want to serve PHP from the same virtual host. Here’s a little hack to make this all possible. If part of your site requires PHP as well, then mod_rails provides an easy means to accomplish that. See below.

The Problem

You have a Rails application and wish to also run a PHP app in the same host. For example, my site (http://www.matt-greer.com) is a Rails application, however my blog is WordPress, and it lives at http://www.matt-greer.com/blog. The problem here is the request for ‘/blog’ looks like a valid Rails route, so by default Apache will send this request to your Rails server and PHP never gets a chance. If you instead request ‘/blog/index.php’, the inclusion of the .php extension is enough to clue Apache in to let mod_php handle it. But having to always manually append ‘index.php’ to all requests in the /blog directory is certainly not ideal and error prone.

Fixing this with Mongrel is easy

Most Rails implementations involve a separate proxy server such as a Mongrel cluster. Solving the rails+php problem in this setup is pretty easy, you just have to tell Apache for certain directories it should handle the request internally, and not pass it off to Mongrel. This is easily accomplished with a rewrite rule, such as:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/blog.*
RewriteRule .* - [L]
 
# all requests that don't meet the 
# above condition get sent off to mongrel

The RewriteCond command says “if the requested URI contains the string ‘/blog’ at the beginning, then apply the following rule.” The RewriteRule says “For all requests do nothing, just handle them internally.” So this rule can be used to keep all requests for the /blog directory internal to Apache, and let mod_php kick in without mongrel getting involved.

Fixing this with mod_rails is even easier!

I’ve came back and edited this post after the fact. Turns out this is very easy to do with mod_rails. You just need to use the PassengerEnabled directive inside a Location directive. This allows you to selectively turn mod_rails on or off on a per directory basis. As an example, here is my host’s apache config file with the relevant bits:

<VirtualHost *:80>
  # ...
  ServerName matt-greer.com
  ServerAlias www.matt-greer.com
  # ...
 
  <Location /blog>
    PassengerEnabled off
  </Location>
</VirtualHost>

And that’s it! Passenger will leave /blog alone, and all is well.

Here is the Phusion documentation on PassengerEnabled.


Tags: , , ,

Leave a Comment