At the Forge - Phusion Passenger

I've been using Ruby on Rails for several years now, and I continue
to marvel at the ease with which I can create sophisticated Web
applications. It's not perfect, but the fact is that Rails has made
the hardest parts of Web development fairly painless. ActiveRecord,
which lets me work with my database almost effortlessly, is obviously
a great achievement, but the other elements of Rails—from database
migrations to the templating system to the overall MVC structure—often surprise me with the elegant solutions they offer to common
problems. The coming merger with Merb, a lean-and-mean alternative to
Rails, leads me to believe that Rails will continue to provide
developers with a terrific environment in which to practice their craft.

So, it's been frustrating to me, and to many other developers as
well, that although Rails makes it easy to write applications, it makes
the deployment of those same applications difficult.
Sure, the famous screencasts in which you can create a blog make it
clear that you can be up and running in almost no time. But, that's
using WEBrick, a simple HTTP server written in Ruby, which no one
realistically would use on a production site.

Apache, the HTTP server I have used since it was first released,
and which continues to power the majority of Web sites in the world,
would appear to be a natural choice for Rails deployment. After all,
Rails is an open-source project, and just about every open-source Web
framework hooks into Apache, right? Unfortunately not. The interface
between Apache and Rails used a protocol known as FastCGI, or
FCGI, and the combination of Rails, FCGI and Apache was long
considered inferior to other options.

There always have been alternatives. Some sites used lighttpd, which
had support for FCGI that was considered superior to what Apache
offered. Others switched to Mongrel, which was designed in part to
provide a stable and fast option for Rails applications. Some sites
combined Mongrel with yet another open-source server, nginx
(pronounced “engine-x”), which excels at handling static files. The
book Deploying Rails Applications, which I recommend to anyone
working on production Rails sites, steps through the configuration of
Mongrel and nginx at great length.

For several years, then, deploying a Rails application meant learning
to work with a new set of servers. This had several negative impacts.
First, it raised the bar for using Rails just a bit more; now
programmers needed to learn not only a new framework, but also a new HTTP
server too. Another outgrowth was the relative dearth of hosting
facilities that could work with Rails. PHP is nearly ubiquitous in
the hosting world, in part because it integrates easily with the other
elements of the LAMP stack (Linux, Apache and MySQL). Because Rails
didn't easily integrate with Apache, it meant that hosting providers
would need to learn a new skill and maintain a new package, which they
weren't interested in doing.

And so, it was with a great deal of fanfare that Phusion, a Dutch
consulting firm that has been using Ruby for the last few years,
announced in 2008 that it had released Passenger, otherwise known as
mod_rails, a module for Apache that makes it trivially easy to get
up and running with a Rails application. I have switched to Passenger
for my Rails production sites and have no complaints or regrets about
doing so. And, it seems that I'm not alone; the company that
originally sponsored the development of Ruby on Rails, 37signals, has
indicated that it uses Passenger for some of its applications, and
that it is thinking of moving additional applications to it in the
future.

Yet another advantage to the fact that we can now use Apache to deploy
Rails applications is the availability of other Apache modules.
Apache was designed to be highly modular, letting developers include
the modules they need, while excluding those that would make the
server less efficient. Over the years, this has led to the
development of dozens of different modules for Apache, covering
everything from authentication to logging, from content negotiation to
server administration. Having access to this large pool of useful
modules means that our Rails application can be customized in a large
number of different ways, providing us with many choices when it comes
to deployment.

This month, we look at how to use Passenger to deploy a Rails
application. We also look at how we can combine other Apache
modules with Passenger for a customized application solution.

Installation

Installing Passenger is a remarkably easy process, assuming that you
already have Apache installed on your computer. First, you need to
install the Passenger software, which comes as a Ruby gem:

sudo gem install passenger

This installs the Ruby gem (which on my Ubuntu server, is placed in
/usr/lib/ruby/gems/1.8/gems), as well as several programs in /usr/bin,
which we will use for Passenger. We use the first of these to
install the Passenger module for Apache:

passenger-install-apache2-module

This starts the process of installing the Apache module on your
computer; Passenger's installer script is smart enough to find many
different versions of Apache, in many different places. It looks
through Apache, determines what needs to be installed and then
prompts you to install required packages automatically. For example,
this is the output from the Passenger install program:

Checking for required software...
* GNU C++ compiler... found at /usr/bin/g++
* Ruby development headers... found
* OpenSSL support for Ruby... found
* RubyGems... found
* Rake... found at /usr/bin/rake
* Apache 2... found at /usr/sbin/apache2
* Apache 2 development headers... not found
* Apache Portable Runtime (APR) development headers... found
* Apache Portable Runtime Utility (APR) development headers... found
* fastthread... found
* rack... found

If you are missing one or more of these programs, the installer
tells you what commands you need to run in order to install the
necessary programs. For example, my Ubuntu server indicated that I
needed to install Apache 2 development headers and suggested I
do this by executing the following:

apt-get install apache2-prefork-dev

I followed those instructions, and it worked. Once I finished
installing the additional package via apt-get, I re-ran
passenger-install-apache2-module. This time around, it succeeded,
compiling the Apache module and adding an appropriate LoadModule
directive in the Apache configuration file.

Indeed, now that Passenger is on our system, we can configure one or
more Web sites. A simple configuration—indeed, the shortest
one—would look like this:

Note that the DocumentRoot points to the public directory of the
Rails application, rather than to the Rails root. The Rails
application itself is assumed to reside in the app directory
parallel to public. Assuming that your Rails application is in
place, restarting the Apache server will load the Passenger module,
then run your application. By default, Passenger assumes you
want to run your application using the “production” environment, which
is optimized for system efficiency, rather than programmer
interactivity. You can use the RailsEnv configuration directive to
set the environment to something else, however:

RailsEnv development

Once your server is running, Apache continues to produce its
standard log files (that is, error, access and referrer). Rails
also will produce its standard log files in the application's log directory,
so if you are used to looking through logs/production.log, you need
not fear that it will be going away.

To restart the Rails application, you need to create a file called
restart.txt in the application's tmp directory. Once this file is
created, Passenger restarts the application, making sure not to
interrupt any HTTP requests that it is currently servicing. (In this
way alone, it is clearly superior to restarting Apache completely.)