Using RVM rubies with Passenger

RVM will allow you to use any of it’s MRI/YARV rubies with passenger very easily.

Passenger

Passenger is essentially ‘mod_ruby’ for both Nginx and Apache. You may select *exactly one* Ruby to run all of your Passenger Ruby applications with. If you need to run more than one Ruby interpreter then you should choose the most common one as Passenger Ruby. You then use proxy pass to external application servers such as Passenger Standalone, Unicorn, Thin, Mongrel, Mongrel2, etc… in order to accomplish running different applications under different rubies. For a full explanation of this (with pretty pictures!) see the post on Phusion’s Blog

Passenger *3*

Installing Nginx/Apache with Passenger

First of all there’s passenger-install-apache2-module and passenger-install-nginx-module. At the end of the installation it outputs a PassengerRuby configuration snippet for the web server. Its value is set to the RVM Ruby wrapper script that corresponds with the RVM Ruby and RVM gemset that was used to run the installer. This should be all you need for configuration of Passenger 3!

If it’s not, here’s what you might have to do, almost all of this stolen from Darcy’s Blog Post

In your .rvmrc do:

if [[ -s "/Users/sutto/.rvm/environments/ree-1.8.7-2010.02@my-app-name" ]] ; then
  . "/Users/sutto/.rvm/environments/ree-1.8.7-2010.02@my-app-name"
else
  rvm --create use  "ree-1.8.7-2010.02@my-app-name"
fi

Then in the rails project, add a new file config/setup_load_paths.rb and add

if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
  begin
    rvm_path     = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
    rvm_lib_path = File.join(rvm_path, 'lib')
    $LOAD_PATH.unshift rvm_lib_path
    require 'rvm'
    RVM.use_from_path! File.dirname(File.dirname(__FILE__))
  rescue LoadError
    # RVM is unavailable at this point.
    raise "RVM ruby lib is currently unavailable."
  end
end

# Select the correct item for which you use below.
# If you're not using bundler, remove it completely.
#
# # If we're using a Bundler 1.0 beta
# ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
# require 'bundler/setup'
#
# # Or Bundler 0.9...
# if File.exist?(".bundle/environment.rb")
#   require '.bundle/environment'
# else
#   require 'rubygems'
#   require 'bundler'
#   Bundler.setup
# end

Please note that for Passenger 3 you now use the ruby wrapper script directly with no need to use the passenger_ruby wrapper.

Starting Passenger Standalone

Then there’s Passenger Standalone, i.e. ‘passenger start’. Passenger Standalone uses Nginx internally, and it writes a passenger_ruby directive to the Nginx configuration file. This directive points to the RVM Ruby wrapper script that corresponds with the RVM Ruby and RVM gemset that was used to run the ‘passenger start’ command.

Bundler Gotcha

When using Bundler in your project, Passenger will try to be smart and only add to your $LOAD_PATH the gems listed in your Gemfile. This can lead to “unable to load” errors for your unlisted gems (this should only happen during development). You can check your run-time load path by adding

f = File.open('/tmp/load_path', 'w')
f.write($:)
f.close

to your app’s main file (before the “require” calls). You won’t be able to load any gems that are not in that load path.

Passenger *2* with RVM

Select a Passenger Ruby and Generate Wrapper Scripts

Run RVM using your desired Ruby interpreter, and pass the ‘–passenger’ option. This will generate wrapper scripts in RVM’s bin directory (see Notes below). These wrapper scripts ensure environment variables such as GEM_HOME and GEM_PATH are set correctly for applications run by passenger. E.g:

rvm ree --passenger

Alternatively, you can use the rvm wrapper command directly:

rvm wrapper ree@ninjas passenger

Install Passenger

rvm ree
gem install passenger
rvmsudo passenger-install-nginx-module

Or if you are forced to use the tomahawk,

rvmsudo passenger-install-apache2-module

Configure the Web Server

For Nginx users, replace the passenger_ruby line with:

passenger_ruby /home/wayne/.rvm/bin/passenger_ruby;

For apache users, use:

PassengerRuby /home/wayne/.rvm/bin/passenger_ruby

Please note that if you installed rvm as root / are using a system wide ruby, instead of using /home/wayne/.rvm/bin/passenger_ruby as in the above examples, you’ll instead need to use /usr/local/rvm/bin/passenger_ruby.

Notes

  • Add the passenger default user (PassengerDefaultUser/passenger_default_user) to the rvm group. On some systems this is ‘www-data’ and on others it might be ‘http’ or ‘www’. One telling sign that you forgot to do this would be spending the better part of a day trying to figure out bizarre fork-bomb-like symptoms on passenger spawn (::grin::).
  • Do no not forget to configure the production environment and/or to set the rails_env/RailsEnv variable to development into nginx.conf/httpd.conf for the virtual server config block. The RAILS_ENV defaults to ‘production’.
  • Be sure to change ‘/home/wayne’ in the above examples to your own $HOME directory,
  • The ‘.rvm/bin/passenger_ruby’ is actually what is known as a ‘wrapper script’ which sets up the environment for the passenger so that it can find it’s gems, etc… and then exec’s the actual ruby binary.”
  • passenger_root/PassengerRoot Should be something similar to the following, which is for Passenger 2.2.11 installed under ree-1.8.7-2010.01.
     passenger_root /home/millisami/.rvm/gems/ree-1.8.7-2010.01/gems/passenger-2.2.11

Troubleshooting

  • The most common issue is forgetting the /bin/ part of the path to get the proper wrapper script:
  • The next most common issue is listening to the output of the passenger installation script with respect to where passenger_ruby/PassengerRuby are located. Be sure to use the wrapper script location as specified above. To be more clear, see the example below for Nginx config:
    passenger_ruby /home/wayne/.rvm/bin/passenger_ruby;
    * NOTICE THE '.rvm/bin' DIR  ^ ^ ^
    * do NOT use the actual ruby binary in .rvm/rubies/{passenger_ruby}/bin/ruby
    * do not listen to passenger's output for passenger_ruby as passenger is not aware of rvm.

    For system wide (root) installs the bin directory is /usr/local/rvm/bin instead:

    passenger_ruby /usr/local/rvm/bin/passenger_ruby;

FAQ

  • Q: Can I run multiple projects under passenger with each project on a different ruby version?A: Not at this time. Passenger currently only supports running it’s projects under *one* ruby. You can get this behavior using a proxy pass.
  • Q: How do I use custom gemsets under passenger?A: Without bundler you can either set environment variables yourself in your config.ru like:
    ENV["GEM_HOME"]=%x{"source ~/.bash_profile ; rvm ree@pancake ; rvm gemdir"}.strip

    Or, if you are already using rvmrc’s, you can use the rvm ruby api and config/setup_load_paths.rb in recent passenger versions by following the guide located here.

    A: With bundler: Install bundler outside any gemset, switch back to the gemset you wish to use and run bundle install and restart the application (by touching tmp/restart.txt). This works becase bundler stores absolute paths inside .bundle/environment.rb which will be loaded by bundler directly. If this doesn’t work as expected, try running bundle install like so:

    bundle install $BUNDLE_PATH

    How can I use commands like passenger-status in conjunction with a user install but run them as root? Mainly the key to this is to use wildcards in the sudoers file as the following examples show.

    /usr/bin/env GEM_PATH=* GEM_HOME=* PATH=* passenger-status

글쓴이: 최효성

외과전문의,웹프로그래밍,컴퓨터 일러스트레이션 / Surgeon, Medical Illustration, Web Programmer

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중