Passenger for Nginx

I didn’t consider using Passenger when it was first released because it only worked with Apache and I prefer nginx. But now Passenger works with nginx! This is great news. Nginx and Passenger make for simple high-performance Rack and Rails web application deployment. I still like thin. But the simplicity of deploying with Passenger makes it a better solution for my needs. I’ve created a second webfaction-rails-environment installation script that implements Passenger. It’s available at GitHub.

The one potential downside of nginx+Passenger on WebFaction is that the reported RSS is greater than with monit+nginx+thin. In actuality, nginx+Passenger uses far less physical memory (especially with Ruby Enterprise Edition) than any other solution. The reported RSS is higher because of multiple counting. Separate application instances share memory that doesn’t change. If memory usage is metered strictly on the basis of RSS, then you’re not getting your money’s worth of memory using Passenger. “Private Dirty RSS” is a more accurate measure of memory usage. The README of webfaction-rails-environment shows you how to determine it. The difference can be substantial.

Rails Deployment Options

There are many ways to deploy a Rails application. Sorting them all out and finding the right solution for your situation can be confusing. In this post I list and briefly describe popular choices.

Ruby Virtual Machine

Most Ruby implementations can run Rails. Some, however, cannot. The ability to run Rails is a major achievement for alternative Ruby VMs. For detailed comparisons check out Antonio Cangiano’s blog. He does the Ruby shootout.

  • MRI
    • 1.8 standard
    • Ruby 1.8.6 is the recommended version to use with Rails
  • YARV
    • 1.9 standard
    • Significantly faster than MRI
    • Rails is not yet fully compatible with Ruby 1.9
    • Many gems are not compatible with Ruby 1.9
  • JRuby
    • Java implementation of Ruby
    • Runs Rails
  • Rubinius
    • “Ruby in Ruby”
    • Runs Rails
  • Ruby Enterprise Edition
    • From the creators of Passenger
    • Fork of MRI
    • 33% less memory consumption on average when used with Passenger
  • MagLev
    • Commercial
    • Pending release
    • Lots of promise in terms of performance and features, but won’t run Rails for some time

For critical production applications, there are really only two choices to consider. If you are using Passenger, use Ruby Enterprise Edition. Otherwise, use the standard Ruby VM. The other implementations are progressing rapidly and developers are working hard to make them production ready.

Server Configuration

This is an active area. Notable configurations include:

  • nginx + mongrel | thin | ebb | fuzed (yaws)
    • nginx is a powerful lightweight frontend server/reverse proxy/load balancer that can withstand a real pounding
    • mongrel is the veteran backend web server for Ruby on Rails
    • thin is an evented backend server that’s faster than mongrel and supports unix socket connections
    • ebb is an evented backend server written in C that’s faster than thin and also supports unix socket connections, but it uses more memory than thin while idling
    • fuzed allows Rails to be served up by yaws, a server written in Erlang that provides an unparalleled degree of concurrency
  • Apache + Passenger (mod_rails) + Ruby Enterprise Edition
    • New and exciting deployment option for Apache
    • Easy to setup
    • Deploying an app can be as simple is uploading your app
    • mod_rails and Ruby Enterprise Edition, both developed by Phusion, together provide a 33% lower memory footprint (for Rails) on average
    • Integrated monitoring and load balancing; monitors Rails processes and starts/kills them as necessary based on demand
  • LiteSpeed
    • Commercial
    • Relatively easy to setup
    • Better performance than most other solutions
    • Despite its qualities, not a popular choice

I only mention LiteSpeed because of its performance. Few people actually use it for serious Rails deployments. I omitted lighttpd from the list because nginx has stolen the show. Ancient solutions like fastcgi were also omitted.

I use nginx + thin. I have not transitioned to ebb because of higher memory consumption (at least at idle). I included the fuzed project in my list because I find yaws and Erlang fascinating. Yaws puts Apache to shame when it comes to concurrency. I’m not sure how polished the fuzed project is, but it could be a contender. It’s also good to see cooperation between Ruby and Erlang. Mongrel, thin, and ebb are all good options. It all depends on your needs and preferences.

I have not tried out Passenger. It is being touted as a breakthrough solution because of how simple it makes deployment. My first impression is that it is more for deployment novices and conventional shared hosting environments. With WebFaction, you have the freedom and ability to build your own app stack. I’ve made this a breeze with a shake and bake shell script. Nginx is a better frontend server than Apache in its ability to serve static pages and with regard to memory usage. Unfortunately, Passenger only works with Apache.

Load Balancing

Load balancing allows your applications to scale horizontally.

  • Hardware
    • For very large applications
    • Most advanced
    • Expensive
  • HAProxy
    • For large applications
    • Very advanced
    • Difficult to setup
  • nginx-upstream-fair
    • Third party module for nginx
    • Adds fair load balancing to nginx (replaces standard round-robin load balancing)
    • Very simple to setup
    • Small to large applications

I use the nginx-upstream-fair module for load balancing. Written by Grzegorz Nosek, the module works very well and is so easy to setup that there is no reason not to do so.

Monitoring

To make sure that your processes are behaving, you need a process monitor.

I use monit. I haven’t tried the god gem, but I’ve heard good things.