Passenger: Let It Ride?

Mark Cornick, Former Viget

Article Category: #Code

Posted on

Rails application deployment has gotten a pretty bad rep. Legitimate Rails developers and blog trolls alike have bemoaned the lack of something equivalent to mod_php, which would make Rails applications "just work" when uploaded to a web server, as we got used to doing in the PHP days.

So Passenger made a big splash when it was released this month. It promises to make deployment "a breeze" and says "No Ruby on Rails-specific server configuration [will be] required!" Furthermore, the developers' own benchmarks show it being a little faster than Mongrel.

After a decade-plus in IT, I'm skeptical of hype and twice as skeptical of benchmarks. But even though I've mastered the sometimes-confusing realm of Apache and Mongrel, I'm curious to see just how easy it is to use, and just how fast.

I'll save the benchmarks for a future article and concentrate on ease of setup and use. I logged in to a Slicehost VPS running CentOS 5.1 (on x86_64 hardware) and opened the user's guide. The first step is to get the software installed. I chose the gem install:

 $ sudo gem install passenger Building native extensions. This could take a while... Successfully installed rspec-1.1.3 Successfully installed activesupport-2.0.2 Successfully installed activerecord-2.0.2 Successfully installed actionpack-2.0.2 Successfully installed actionmailer-2.0.2 Successfully installed activeresource-2.0.2 Successfully installed rails-2.0.2 Successfully installed passenger-1.0.1 8 gems installed 

So passenger depends on the Rails gems, as well as RSpec. Nothing you wouldn't find in an average Rails application.

Next step is to install Passenger's Apache module. This one-line command attempts to check for needed dependencies before building the code:

 $ sudo passenger-install-apache2-module Welcome to the Passenger Apache 2 module installer. This installer will guide you through the entire installation process. It shouldn't take more than 3 minutes in total. Here's what you can expect from the installation process: 1. The Apache 2 module will be installed for you. 2. You'll learn how to configure Apache. 3. You'll learn how to deploy a Ruby on Rails application. Don't worry if anything goes wrong. This installer will advise you on how to solve any problems. Press Enter to continue, or Ctrl-C to abort. 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/httpd * Apache 2 development headers... found at /usr/sbin/apxs * Apache Portable Runtime (APR) development headers... found * fastthread... found -------------------------------------------- [...] 

Unfortunately, it missed one dependency which I didn't have installed: the headers for libuuid, which are provided in RHEL/CentOS by the e2fsprogs-devel RPM. So let's install that and try again:

 $ sudo yum -y install e2fsprogs-devel [...] Installed: e2fsprogs-devel.i386 0:1.39-10.el5_1.1 e2fsprogs-devel.x86_64 0:1.39-10.el5_1.1 Complete! $ sudo passenger-install-apache2-module [...] The Apache 2 module was successfully installed. Please edit your Apache configuration file, and add these lines: LoadModule passenger_module /usr/lib64/ruby/gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.so RailsSpawnServer /usr/lib64/ruby/gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-server RailsRuby /usr/bin/ruby After you restart Apache, you are ready to deploy any number of Ruby on Rails applications on Apache, without any further Ruby on Rails-specific configuration! 

OK, much better. After adding those three lines to /etc/httpd/conf.d/passenger.conf and restarting, we are ready to configure an application in Apache. According to the final output of the passenger-install-apache2-module program, this is all we need:

 <VirtualHost *:80> ServerName www.yourhost.com DocumentRoot /somewhere/public </VirtualHost> 

Seriously? OK, let's go into the Apache configuration and comment out all of our mod_proxy and mod_rewrite configuration for our application, leaving just the lines mentioned above, and restart Apache...

Splat! Not quite there yet. We get our 500 error page. A quick look at the log reveals:

 ActionView::TemplateError (undefined method `markdown' for #<ActionView::Base:0x 2aaaaba0ed50>) on line #1 of stories/index.html.erb: 1: <%= render :partial => 'story', :collection => @stories %> 

That's interesting, because bluecloth.rb is in our vendor/ directory. But let's try again after installing the BlueCloth gem. Nope, still getting the 500 error. We need to tell the application to restart. We do this by creating a file called "restart.txt" in our app's tmp/ directory:

 $ sudo gem install BlueCloth Successfully installed BlueCloth-1.0.0 1 gem installed $ cd current/tmp/ $ touch restart.txt 

Well, that apparently wasn't enough. Only after restarting the entire Apache process did the 500 error go away. Not too reassuring. Let's try modifying the code, then touching that restart.txt file again to see if the change gets picked up.

 $ vim app/controllers/stories_controller.rb [... change some code ..] $ touch tmp/restart.txt 

This time it worked. Maybe certain things need a "hard" restart? I'm not sure why code located right in vendor/ didn't get loaded, but my gems in vendor/gems/ did. In any case, arranging for Capistrano to create this tmp/restart.txt file is pretty simple; just add this to your Capfile:

 namespace :deploy do desc 'Signal Passenger to restart the application.' task :restart, :roles => :app, :except => { :no_release => true } do run "touch #{release_path}/tmp/restart.txt" end end 

So there you go. Aside from the hiccup with loading bluecloth.rb, it really does work as advertised. In a future article we'll see if those benchmarks really stand up.

Related Articles