Running Ruby on Rails with mod_fcgid and Apache

I had a particularly painful experience trying to get Rails and FCGID to play nicely. It seemed most of what I found was for older versions of rails working with FastCGI.

(UPDATE: See bottom of post – Phusion Passenger makes running Rails under Apache so much easier than configuring mod_fcgid )

So here’s my pass at getting it setup under a Linux environment

First off, I’m using

  • Apache 2.0.52
  • mod_fcgid version 1.10
  • Ruby 1.8.4
  • Rails 1.2.3

Assuming that this is more of a production type setup, put your entire rails project in a directory (assuming you want this to be separate from your development location). I’ll refer to this directory as [rails app]. [rails app] should be the directory that contains the public, app, config, etc directories.

Now, edit your config/database.yml file and make sure that the production database configuration is correct.

I don’t believe that any extra libraries are needed to make rails work with FCGI – I believe they are all built-in now.

Next, in the public directory, you’ll need to edit the .htaccess file. By default rails starts this file with

# General Apache options
AddHandler fastcgi-script .fcgi

AddHandler cgi-script .cgiOptions +FollowSymLinks +ExecCGI

You’ll want to change this part to read

# General Apache options

AddHandler fcgid-script .fcgi

Options +FollowSymLinks +ExecCGI

so that .fcgi is handled by fcgid instead of fastcgi. I removed the .cgi entry just because I wanted to ensure I was getting it working via the mechanism I intended. Also note the 500 error message at the bottom of the .htaccess file – if you’ve gotten Apache configured to get to this directory correctly and something else is going wrong, this is the error message you’ll see. If you’re trying to debug, it can be useful to change this to ensure you’re really working with what you think you are.

Next, and VERY important (no – I didn’t lose 5 hours of my life on this…). You must change the ownership of ALL the files (or at least some critical number of them, I never figured out which magical files mattered) to the user that Apache will try to run them as. This may be apache, or some other user if you have, for instance ,an SuexecUserGroup directive. Ensure that dispatch.fcgi has read/execute permissions Also, the rails apps log and tmp directories must be writable by the user rails is being run as. If the user is incorrect, fcgid won’t run the files, and you’ll get the error message from your .htaccess file, and very unhelpful error_log entries.

One other important thing to note. If any of your Ruby code writes to the console with puts or equivalent, this breaks the rails integration with mod_fcgid. If you wanted to be really sneaky, you could probably do something clever in the dispatch.fcgi file and override the common console output functions to write to a log file or something, but I leave that up to you.

Now on the Apache end:

First make sure mod_fcgid is loaded. In your httpd.conf (or in a conf.d/… config file if you prefer) you’ll need to have the following (with the correct path to your modules directory)

LoadModule fcgid_module /usr/lib/httpd/modules/mod_fcgid.so
<IfModule mod_fcgid.c>
    AddHandler fcgid-script .fcgi .fcg .fpl
</IfModule>
<IfModule mod_fcgid.c>
  SocketPath /var/lib/apache2/fcgid/sock
  DefaultInitEnv  HTTP_RAILS_ENV production
  IdleTimeout 600
  ProcessLifeTime 3600
  MaxProcessCount 8
  DefaultMinClassProcessCount 3
  DefaultMaxClassProcessCount 4
  IPCConnectTimeout 80
  IPCCommTimeout 48
</IfModule>

Note the HTTP_RAILS_ENV setting in there. If you don’t want to run in production, you can change that here. YOU MUST ALSO ADD the following line NEAR THE TOP of your config/environment.rb file – I put it right under the 3 commented lines already in the file.   Apparently based on this article the mod_fcgid has limitations on the environment variables it can set (looks like they have to start with HTTP_??). The following line simply sets the RAILS_ENV to the value of HTTP_RAILS_ENV unless it’s already been set.

# Uncomment below to force Rails into production mode when
# you don't control web/app server and can't set it the proper way
# ENV['RAILS_ENV'] ||= 'production'

ENV['RAILS_ENV'] ||= ENV['HTTP_RAILS_ENV']

This line must be before any of the rest of the rails environment gets loaded or else the environment will initialize in development mode

To actually map in your rails application into Apache, I saw two ways, but I’ve only tried one. I had success with creating a symbolic link in my web servers root directory to the [rails app]/public directory (this of course requires that you have Options FollowSymLinks set). This puts the rails app at http://your site.com/[linkname] The other would be to have inside your VirtualHost directive an Alias directive such as Alias /myRailsApp [rails app]/public .

For either method I believe you’ll need an entry in the VirtualHost directive of your Apache configuration with something like the following

  <Directory [rails app]/public>
    Options Indexes FollowSymLinks ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>

Now, if I haven’t forgotten anything, if you restart Apache, you should be able to access your rails app. Note that this puts your rails application under a subdirectory on the webserver. I haven’t tried to place a rails app as the root of the server, but hopefully this will help you get started.

Note that once you actually get into the rails world, errors, etc will be logged in [rails app]/log. If you didn’t make it into rails, check the apache error_log (note that your sites error log may not be in /var/log/httpd/error_log or the like if there a specific CustomLog directive for the VirtualHost).

Good luck!

Updates

8/16/2007: Discovered a problem with using DefaultInitEnv of RAILS_ENV and the need to use the HTTP_RAILS_ENV setting

1/26/2010: Should have posted this a while back, but somewhere around July/Aug 2009 I heard about Phusion Passenger and it made all of this pain go away.  The installation is very straightforward.  They have a gem which builds the required apache module, etc (see instructions).  I switched my test and production environments at the time over to this and didn’t have any problems (after I removed all the crap I had put in my configs to make rails run under mod_fcgid).  I’ve since switched hosting providers and it also worked well there in FreeBSD.

About these ads

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: