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.
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:
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:
<VirtualHost *:80> ServerName www.mysite.com DocumentRoot /home/reuven/public </VirtualHost>
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:
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.)
Practical books for the most technical people on the planet. Newly available books include:
- Agile Product Development by Ted Schmidt
- Improve Business Processes with an Enterprise Job Scheduler by Mike Diehl
- Finding Your Way: Mapping Your Network to Improve Manageability by Bill Childers
- DIY Commerce Site by Reven Lerner
Plus many more.