Managing multiple mod_passenger standalone configurations

If you’re deploying multiple Ruby/Rails apps with passenger, you might end up with different ruby version requirements. Or maybe you want to keep gemsets separate. For whatever reason, you end up running one or more of your apps in a standalone passenger server and proxying them through Apache or nginx.

Or maybe you’re doing mass webhosting with only passenger standalone instances. Whatever floats your boat.

This is the script I hacked together for Toptranslation. Instructions below.

#!/bin/bash

### BEGIN INIT INFO
# Provides:          passenger-standalone
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Easily start or stop standalone passenger instances
### END INIT INFO

# default config
USER=www-data
APP_DIR=
RVM_RUBY=1.9.2
ADDR=127.0.0.1
PORT=3000
ENVIRONMENT=production

if [ -n "$2" -a -r "/etc/passenger-standalone.d/$2" ]; then
  CONFIG="$2"
elif [ -r "/etc/passenger-standalone.d/$(basename $0)" ]; then
  CONFIG="$(basename $0)"
fi

if [ -n "$CONFIG" ]; then
  if [ ! -r "/etc/passenger-standalone.d/$CONFIG" ]; then
    echo "Error: Configuration '${CONFIG}' not found in /etc/passenger-standalone.d/" >&2
    exit 4
  fi
  source "/etc/passenger-standalone.d/$CONFIG"
  if [ -z "$APP_DIR" ]; then
    echo "Error: APP_DIR is not defined."
    exit 5
  fi
  CMD_START="cd $APP_DIR; rvm use $RVM_RUBY; passenger start -a $ADDR -p $PORT -e $ENVIRONMENT -d"
  CMD_STOP="cd $APP_DIR; rvm use $RVM_RUBY; passenger stop -p $PORT"
fi

. /lib/lsb/init-functions
case "$1" in
  start)
    echo "Starting passenger for ${CONFIG}"
    echo "[$USER] $CMD_START"
    su - $USER -c "$CMD_START"
    ;;
  stop)
    echo "Stopping passenger for ${CONFIG}"
    echo "[$USER] $CMD_STOP"
    su - $USER -c "$CMD_STOP"
    ;;
  *)
    echo "Usage: $0 start|stop [config]" >&2
    exit 3
    ;;
esac

To use, first put it into /etc/init.d/passenger-standalone. Then, for each standalone instance you want to start, create a configuration file in /etc/passenger-standalone.d/ with a sensible name. For example, here’s a redmine configuration:

# /etc/passenger-standalone.d/redmine 
USER=www-data
APP_DIR=/opt/redmine
RVM_RUBY=1.8.7-p330
ADDR=127.0.0.1
PORT=3081
ENVIRONMENT=production

And here is the corresponding VirtualHost for Apache:

<VirtualHost *:80>
  ServerName redmine.example.com
  DocumentRoot /opt/redmine/public

  PassengerEnabled Off
  ProxyRequests Off
  <Proxy *>
    Order deny,allow
    Allow from all,
  </Proxy>
  ProxyPass / http://127.0.0.1:3081/
  ProxyPassReverse / http://127.0.0.1:3081/
</VirtualHost>

Now, when you reload apache with that config and try to access redmine.example.com, you will get an Error 500 because the passenger instance is not running yet. To start it, simply run /etc/init.d/passenger-standalone start redmine, OR symlink /etc/init.d/passenger-standalone to /etc/init.d/redmine and run /etc/init.d/redmine start.

To automatically run the script in the appropriate runlevels, symlink it as described, then run update-rc.d redmine defaults. This will set up the appropriate symlinks.

Update: Fixed a backtick that wasn’t supposed to be there.

3 Replies to “Managing multiple mod_passenger standalone configurations”

  1. Very awesome article, thanks for sharing.

    One thing found while copy and pasting into my system:

    "Error: Configuration `${CONFIG}’

    shoudn’t have the backtick, but a single quote, otherwise it generates a syntax error.

  2. Very nice script! I use on my local machine as on my remote sever, cause I have multiple app’s with nearly all different rubies.

    Tnx alot!

Comments are closed.