RVM + Monit + Passenger + nginx + multiple rubies

Posted by Anton Katunin on 14 June 2011

I've spent a lot of time setting up my host, would like to share my experience.

So what we ve got:
VPS box with ssh access
Two websites, both ruby on rails:
1. Custom website (ruby 1.9.2 + rails 3)
2. Redmine (ruby 1.8.7 + rails 2)
Passeger - to run websites
Monit - to do monitoring and management of processes

VPS was already preconfigured with Nginx and ruby 1.9.2 as system wide setup, so there are no problems of running the first website, as it will work straight out of the box.

The question is how to setup both web applications with different ruby versions.

As we are hosting applications on different ruby versions, we cannot host them together on the same passenger, so we need to setup proxy on the system wide nginx to run the second website as a standalone application.

The access to the second site will look like that:
1. Request comes in to the global nginx
2. The request is proxied to standalone Passenger, which is running on the second instance of nginx

First of all we need to install 1.8.7 ruby on our host. The best way to do that is to use RVM, and install it locally as a current user. I would personally don't recommend to install it system wide. The are many good tutorial how to do that, so i'll skip over that:
http://beginrescueend.com/rvm/install/

After RVM is install and running 1.8.7 ruby version, we need to decide how we will host our second application. For this example I run standalone passenger, which is simply an instance of nginx running passenger with single application. This setup is enough, if there is only one site, otherwise we need to setup a separate second instance of nginx for 1.8.7 ruby.

Because it is only possible to have a single ruby version active at the same time, it could lead into extra problems if we don't do it properly. The best way i've found to do that is to wrap 1.8.7 ruby passenger into separate aplication.
1. You need to switch rvm to the required ruby version (1.8.7 in our case)
2. Install passenger gem if its not already installed
3. Use RVM wrapper to wrap passenger gem, something like:

rvm wrapper 1.8.7@default redmine passenger

That command will create an executable in
where/rvm/installed/.rvm/ruby-1.8.7/bin/

Now you can test it. Navigate to folder with 1.8.7 application and type

redmine_passenger start

This will start passenger server for 1.8.7, and doesn't matter what is the current RVM environment is setup, this will always use 1.8.7 ruby. You should be able to see you application running at localhost:3000 (by default)

So the second passenger is up and running, we need to setup a proxy on the system wide nging to route requests to the second. This is a good information: http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions/

Pretty much we need to add new virtual host to the system wide nginx.

server { listen 80; server_name www.site.com; root /webapps/site.com/public; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; }}

After nginx is restarted, all requests should be routed to the second passenger.

At this point, it is all good, you some people can leave it here. The problem with the current implementation, the system wide nginx instance will start automatically after system start, but the second passenger we need to start manually.

Solution is to use Monit.
http://mmonit.com/monit/documentation/monit.html
Monit is simply is a separate process, which monitors other processes and makes sure all of the up and running.

This is my monit configuration file to start and monitor passenger for 1.8.7 as a separate process.

Monit config:

check process redmine_passenger
with pidfile /var/rapp/redmine/passenger.3000.pid
start program = "/bin/su - user -c '/var/rapp/.rvm/bin/redmine_passenger start /var/rapp/redmine/ -a 127.0.0.1 -p 3000 -d -e production' "
stop program = "/bin/su - user -c '/var/rapp/.rvm/bin/redmine_passenger stop /var/rapp/redmine/' "

Replace user with current user. Also notice that there is a space before and after user.

And finally, if you are stuck, here are some good website, which helped me to get my solution.

References:
http://groups.google.com/group/rubyversionmanager/browse_thread/thread/d1a6c1f6396a8bf6/51afece4c8943912?#51afece4c8943912

http://groups.google.com/group/rubyversionmanager/browse_thread/thread/d1a6c1f6396a8bf6/279b6dacdf898d0a?#279b6dacdf898d0a

https://gist.github.com/960540

http://matthew.mceachen.us/blog/howto-make-system-wide-rvm-installations-work-with-cron-monit-delayed_job-and-passenger-1021.html

http://stackoverflow.com/questions/5863815/monit-rvm-thin-on-osx-linux

https://github.com/romanbsd/passenger_monit

http://rushthinking.com/using-monit/


Read next:

Gate's law