Phusion Passenger & running multiple Ruby versions
UPDATE February 27 2013: this article has been obsolete. Phusion Passenger supports multiple Ruby interpreters as of version 4.0.0. The PassengerRuby config option has been made a per-virtual host option, so you can customize your Ruby interpreter on a per-application basis.
One of the questions we’ve been getting a lot lately is whether it’s possible to run multiple Ruby versions with Phusion Passenger, e.g. have app A and B run on Ruby 1.8.7 while having app C run on Ruby 1.9.2. In previous versions of Phusion Passenger there were ways to get around that, e.g. by mixing in Mongrels. As of Phusion Passenger 3 you can run all components as Phusion Passenger.
The setup that we currently recommend is to combine Phusion Passenger for Apache or Phusion Passenger for Nginx, with Phusion Passenger Standalone. One must first identify the Ruby version that you use most. One then proceeds with setting up Phusion Passenger for Apache or Phusion Passenger for Nginx to use that Ruby version. All applications that are to use a different Ruby version can be served separately through Phusion Passenger Standalone and hook into the main web server via a reverse proxy configuration.
Example

Suppose that you have four websites:
- foo.com, to run on Ruby 1.8.7.
- bar.com, to run on Ruby 1.8.7.
- fries.com, to run on Ruby 1.9.1.
- hamburgers.com, to run on Ruby 1.9.2.
And suppose that you’re using RVM to manage these Rubies.
Setting up foo.com and bar.com (Ruby 1.8.7)
The Ruby version that you use most is Ruby 1.8.7, so you setup Apache or Nginx to use Ruby 1.8.7 and to serve foo.com and bar.com.
rvm use 1.8.7 gem install passenger --pre # Then one of: passenger-install-apache2-module passenger-install-nginx-module
# Partial Apache configuration
PassengerRuby /home/someuser/.rvm/wrappers/ruby-1.8.7/ruby
<VirtualHost *:80>
ServerName www.foo.com
DocumentRoot /webapps/foo.com/public
</VirtualHost>
<VirtualHost *:80>
ServerName www.bar.com
DocumentRoot /webapps/bar.com/public
</VirtualHost>
# Partial Nginx configuration
passenger_ruby /home/someuser/.rvm/wrappers/ruby-1.8.7/ruby
server {
listen 80;
server_name www.foo.com;
root /webapps/foo.com/public;
passenger_enabled on;
}
server {
listen 80;
server_name www.bar.com;
root /webapps/bar.com/public;
passenger_enabled on;
}
foo.com and bar.com have now been deployed on Phusion Passenger for Apache or Phusion Passenger for Nginx, and running on Ruby 1.8.7.
Setting up fries.com (Ruby 1.9.1)
The next step is to start fries.com in Phusion Passenger Standalone using Ruby 1.9.1. Since port 80 is already used by Apache or Nginx, we use start Phusion Passenger Standalone on a different port.
rvm use 1.9.1 gem install passenger --pre cd /webapps/fries.com passenger start -a 127.0.0.1 -p 3000 -d
Fries.com is now running on localhost port 3000 as a background daemon. Next, connect it to Apache or Nginx via a reverse proxy.
# Partial Apache configuration
<VirtualHost *:80>
ServerName www.fries.com
DocumentRoot /webapps/fries.com/public
PassengerEnabled off
ProxyPass / http://127.0.0.1:3000
ProxyPassReverse / http://127.0.0.1:3000
</VirtualHost>
# Partial Nginx configuration
server {
listen 80;
server_name www.fries.com;
root /webapps/fries.com/public;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
}
Setting up hamburgers.com (Ruby 1.9.2)
We do the same thing for hamburgers.com. Port 3000 is already in use, so we assign it to port 3001.
rvm use 1.9.2 gem install passenger --pre cd /webapps/hamburgers.com passenger start -a 127.0.0.1 -p 3001 -d
Then we hook it up to the web server via reverse proxying.
# Partial Apache configuration
<VirtualHost *:80>
ServerName www.hamburgers.com
DocumentRoot /webapps/hamburgers.com/public
PassengerEnabled off
ProxyPass / http://127.0.0.1:3001
ProxyPassReverse / http://127.0.0.1:3001
</VirtualHost>
# Partial Nginx configuration
server {
listen 80;
server_name www.hamburgers.com;
root /webapps/hamburgers.com/public;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}
}
Performance tip
Phusion Passenger Standalone also supports listening on a Unix domain socket instead of a TCP socket. Unix domain sockets are significantly faster than TCP sockets.

Only Nginx supports reverse proxying to Unix domain sockets; Apache does not support this.
In order to make Phusion Passenger Standalone listen on a Unix domain socket, you need to run it with Nginx 0.8.21 or higher. In fact we contributed support for Unix domain sockets to Nginx specifically for this feature!
Start Phusion Passenger Standalone like this:
passenger start --socket /tmp/fries.com.socket -d --nginx-version 0.8.50
The --socket option tells Phusion Passenger to bind to the given Unix domain socket. The --nginx-version option tells Phusion Passenger Standalone to use Nginx 0.8; 0.7 is the default.
Next you must setup an Nginx upstream block with the Unix domain socket as the only entry. Then setup Nginx to reverse proxy to the created upstream block.
upstream fries_upstream {
server unix:/tmp/fries.com.socket;
}
server {
listen 80;
server_name www.fries.com;
root /webapps/fries.com/public;
location / {
proxy_pass http://fries_upstream;
proxy_set_header Host $host;
}
}
It should be noted that Phusion Passenger for Apache and Phusion Passenger for Nginx already use Unix domain sockets internally for optimal performance. In fact we’ve done this since version 1.0. We plan on elaborating more about our internal technologies in a future blog post.
Conclusion
Those of you who are familiar with Mongrel and Thin will see the similarity. Indeed, Phusion Passenger Standalone was designed to be able to used in a reverse proxy environment such as the one demonstrated in this article. Unlike Mongrel and Thin clusters however you only need a single Phusion Passenger Standalone instance per web application and thus only a single address to proxy to. Phusion Passenger Standalone will take care of starting and stopping application processes for you and will make sure processes are restarted when they crash.
var addthis_config = {"data_track_clickback":true,"data_ga_property":"UA-32583440-3","data_ga_social":true,"data_track_addressbar":false,"data_track_textcopy":false,"ui_atversion":"300","ui_508_compliant":true}; var addthis_product = 'wpp-3.1';
Phusion. All rights reserved.
Pingback: Link dump for September 21st | The Queue Blog
Pingback: The MetaSpring Blog Carnival: Issue 9 – Ruby On Rails
Pingback: Rodando multiplas versões do Ruby com Phusion Passenger | Guru-CE
Pingback: Phusion Passenger 3.0.0 最终版发布-传播、沟通、分享-一直“有你”
Pingback: passenger多ruby版本共存部署- 朗志工作室(Langzhi Studio) | 黄金屋
Pingback: links for 2011-01-07 « Bloggitation
Pingback: links for 2011-05-24 « Caiwangqin’s delicious bog
Pingback: Running passenger with multiple different ruby versions apache nginx rvm | Rob Aldred
Pingback: RVM and Passenger integration « Ruby on Rails Outsourcing
Pingback: javanna.net » Blog Archive » Redmine behind Apache with Passenger » javanna.net
Pingback: Ruby 1.8 and Ruby 1.9 with Phusion Passenger and Apache (and Thin) | Jalada
Pingback: Using RVM rubies with Passenger « Ruby on Rails
Pingback: RVM と Phusion Passenger を使って複数の Ruby, Ruby on Rails アプリケーションを動かそう | ユニキャストラボ
Pingback: Installing phusion passenger with apache2 on Ubuntu « srisoham
Pingback: Web FAQ » passenger and nginx stand alone
Pingback: Default ruby in server | PHP Developer Resource
Pingback: Install and Setup RVM
Pingback: How to try out puma with Apache Proxy right now | kangaroo court