Setting up Passenger Standalone, RVM and launchd on OS X
April 27, 2011
Installing Radiant with Passenger (Standalone), RVM and Launchd on OS X
Introduction - why Passenger Standalone
I like to deploy all my basic sites on the same host. For example, deploying a Radiant site along with a few small Rails sites on the same box. This keeps things easy for me, and no sense devoting a lot of resource if I know the site will be fairly small.
However, this poses some deployment challenges.
I want to use Passenger, like all the cool kids are doing. Just set up some Apache things and I’m ready to go.
I also always use RVM. It is so amazing being able to keep project gems separate from each other. This is especially important when you have multiple projects on the same machine.
This sounds like a dream team: use Apache/Passenger to host multiple Rails apps, with separate gemsets, end of story.
Except, the real world doesn’t work like that.
First, your rvm and Passenger must share a common Ruby. If they can’t, you must use Apache Reverse Proxy cleverness with other servers (like Passenger Standalone).
The easy way to avoid this mess is to make sure they match. We’re all using REE anyway, amiright?
Actually, usually not. If you’re on a shared host, or host multiple Ruby sites from one box, you don’t want to make everyone on that site use REE… even if it’s the best.
For example, what happens in a year when you’re working on a Rails 3 site in Ruby 1.9… you just forced yourself into yesterday’s version.
It is tempting to set up Passenger to use one Ruby (REE) and point Passenger to your gemsets. I really suggest you go to the extra work and set up this system instead
Setting up Apache as a Proxy
So, we want to use Apache as a front-end, and use reverse proxies to run all these sites on their own Passenger standalone servers.
In your Apache configuration (in /etc/apache2/sites, in a file that increments the leading count):
<VirtualHost: *:80>
ServerName cms.example.com:80
ProxyPass / localhost:3000/
ProxyPassReverse / localhost:3000/
</VirtualHost: *:80>
Note: that trailing slash is important
If you have your Rails/Radiant site on the server, at this point you should be able to fire up Passenger (passenger start in your Radiant folder), visit your server name, and have it redirected.
This Passenger instance will run as long as you are connected, or as long as the machine stays up (whichever ends first). But that won’t do for a production webserver…
Making Your Passenger Get Up, And Stay Up (OS X)
Figuring out what command to give launchd
This goal is not as obvious as it might seem. We want a Passenger Standalone instance to be up all the time, including after machine restarts. So, how do we best do this?
In the past, for demonstration purposes, I’ve SSHed into a server, fired up GNU Screen, ran passenger, then detected the screen. GNU Screen will keep the SSH socket open (from the server’s perspective, anyway), and thus Passenger. This solution works, but it’s a hack.
Ideally I want to keep Passenger up without this hack, or other similar “poll based” monitoring methods.
Launchd to the rescue.
Here’s how to get that up:
-
Create a rvm wrapper:
$ rvm wrapper RUBY@GEMLIST radiant_site
Will create ~/.rvm/bin/radiant_site_ruby
So if you’re running ree with your gemset name “radiant_site”
$ rvm wrapper ree@radiant_site radiant_site
Which creates a Ruby named radiant_site_ruby.
-
Find out where your passenger is:
which passenger
Your command to start up your Rails site is an amalgamation of these three things and the path to your Rails root:
/Users/aias/.rvm/bin/radiant_site_ruby /Users/aias/.rvm/gems/ruby-1.8.7-p299@radiant_site/bin/passenger start PATH TO SITE -e production
Try this command on the command line before pouring it into a launchd script.
Pouring it into Launchd
Launchd has two interesting features which we’ll use here:
- KeepAlive: Launchd will make sure your progress stays up, restarting if neccisary
- UserName: run the command as a particular user
My Launchd file is here:
Save your version of this file to /Library/LaunchDaemons/
- you want this to launch even if your user is not logged in.
Load the file with: sudo launchctl load /Library/LaunchDaemons/FILE NAME
Launchd Debugging Notes
- launchd scripts must be owned by root:wheel. (Lingon does not save files this way)
- Use
StandardErrorPath
andStandardOutPath
to debug these. Note that the files must exist first, and be writable by root. These are amazingly useful files to have to see what your job is going. - Seriously, you do not want the -d flag for Passenger. (It makes the whole thing not work - launchd has rules about what you can and can’t do in
KeepAlive
/LaunchDaemon mode)
But what about Passenger Standalone on Linux?
I haven’t tried either of these out, but they look like they would fit the bill.