Setting up Nginx with Ruby on Rails using Passenger and Ruby Enterprise Edition

In the first article of this series I reviewed the steps I took to secure the server and get a basic, reasonably secure set up. The next step is to get Nginx setup for ruby. I chose Nginx because of it’s low memory usage, which is important when trying to squeeze the most out of a smaller VPS.
Setting up Ruby Enterprise Edition:

I’m going to use Ruby Enterprise Edition exclusively for my ruby apps. Again, this is to optimize memory usage on the system.
First install a few prerequisites:
sudo aptitude install libssl-dev libreadline5-dev
Get a directory ready for loading source into:
mkdir ~/sources cd ~/sources mkdir ree cd ree
Get the ruby code and run the installer (be sure to get the latest version). I just accepted the defaults when running the installer. If you change any directories, you’ll need to make the same changes below. Also if you use a different version of ruby enterprise edition, you may need to update the paths below.:
wget http://rubyforge.org/frs/download.php/58677/ruby-enterprise-1.8.6-20090610.tar.gz tar zxf ruby-enterprise-1.8.6-20090610.tar.gz sudo ./ruby-enterprise-1.8.6-20090610/installer
Now use links to make this the primary ruby installation:
sudo ln -s /opt/ruby-enterprise-1.8.6-20090610/bin/ruby /usr/local/bin/ sudo ln -s /opt/ruby-enterprise-1.8.6-20090610/bin/gem /usr/local/bin/ sudo ln -s /opt/ruby-enterprise-1.8.6-20090610/bin/rake /usr/local/bin/ sudo ln -s /opt/ruby-enterprise-1.8.6-20090610/bin/rails /usr/local/bin/
Verify the installation and links with:
which ruby // should be /usr/local/bin/ruby which gem // should be /usr/local/bin/gem which rake // should be /usr/local/bin/rake which rails // should be /usr/local/bin/rails
Now update and install passenger:
sudo gem install rubygems-update sudo gem install passenger
Setting up Nginx with Passenger Support:
We have to compile Nginx from source to integrate passenger support.
First install a few prerequisites:
sudo aptitude install libc6 libpcre3 libpcre3-dev libpcrecpp0 libssl0.9.8 libssl-dev zlib1g zlib1g-dev
Now get the Nginx source (be sure to get the latest version):
cd ~/sources mkdir nginx cd nginx wget http://sysoev.ru/nginx/nginx-0.7.61.tar.gz tar zxf nginx-0.7.61.tar.gz cd nginx-0.7.61
Configure the build to use passenger (be sure to use the path for the version of ruby you installed in the add-module section):
sudo ./configure --sbin-path=/usr/local/sbin --with-http_ssl_module --add-module=/opt/ruby-enterprise-1.8.6-20090610/lib/ruby/gems/1.8/gems/passenger-2.2.4/ext/nginx
Now build, install and start nginx:
sudo make sudo make install sudo /usr/local/sbin/nginx
You’ll see a warning about passenger being disabled. We’ll fix that in a minute. Now you can navigate to the nginx welcome page using http://”your ip address”. The page should say “Welcome to nginx”.
When installed from source, the nginx initialization script doesn’t get created, so lets stop nginx and create that now:
sudo kill `cat /usr/local/nginx/logs/nginx.pid` sudo nano /etc/init.d/nginx
Copy and paste this into the nginx script file:
#! /bin/sh
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi
set -e
. /lib/lsb/init-functions
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/usr/local/nginx/logs/$NAME.pid --exec $DAEMON || true
sleep 1
start-stop-daemon --start --quiet --pidfile \
/usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
status)
status_of_proc -p /usr/local/nginx/logs/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
exit 1
;;
esac
exit 0
Make sure the script is executable and ensure that it starts when the system boots:
sudo chmod +x /etc/init.d/nginx sudo /usr/sbin/update-rc.d -f nginx defaults
Now you can start, restart, stop nginx using the commands:
sudo /etc/init.d/nginx start sudo /etc/init.d/nginx restart sudo /etc/init.d/nginx stop
I like to set up my web sites in directories similar to the approach the apache server takes. This involves setting up a few directories and breaking up the default nginx config file into smaller ones.
First create the directories. Sites-available is where our site configurations will go and sites enabled will only contain our active sites:
sudo mkdir /usr/local/nginx/sites-available sudo mkdir /usr/local/nginx/sites-enabled
Now backup the default config file and create a new one for the default web site. You may want to refer back to the config file to set up a default ssl site:
sudo cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.back sudo nano /usr/local/nginx/conf/nginx.conf
Now copy and paste this into the nginx.conf file. If you used a different version or install location for ruby enterprise edition, be sure to update the passenger statements below with the correct path.:
user www-data www-data;
worker_processes 4;
events {
worker_connections 1024;
}
http {
passenger_root /opt/ruby-enterprise-1.8.6-20090610/lib/ruby/gems/1.8/gems/passenger-2.2.4;
passenger_ruby /opt/ruby-enterprise-1.8.6-20090610/bin/ruby;
server_tokens off;
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 5;
tcp_nodelay off;
gzip on;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml
application/xml application/xml+rss text/javascript;
include /usr/local/nginx/sites-enabled/*;
}
Now we’ve included the initialization for passenger, so our warning about passenger being disabled should go away. We’re also telling nginx to include our sites-enabled directory, so any sites we link to that directory will be served up.
We’re in the home stretch, we just need a default site set up:
sudo nano /usr/local/nginx/sites-available/default
Copy and paste this into the file:
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
Now we just need to enable the site and restart nginx:
sudo ln -s /usr/local/nginx/sites-available/default /usr/local/nginx/sites-enabled/default sudo /etc/init.d/nginx restart
That will be the procedure for any sites you want nginx to serve. Create a configuration file in the sites-available folder and then create a symlink to the sites-enabled folder to enable it. If you want to remove a site, just remove the link in the sites-enabled folder. Always restart nginx to see the changes.
You can verify the installation by going back to http://”your ip address”. You should see the “Welcome to nginx” page.
For sites that use ruby, you’ll need to include “passenger_enabled on;” in their configuration as shown here:
server {
listen 80;
server_name www.yourSiteName.com;
location / {
root /pathToTheSiteFiles;
index index.html;
passenger_enabled on;
}
}
Okay, now the web server is set up and we’re ready to serve up our ruby apps with passenger. Next we’ll get php going and then start installing some apps.

[...] Setting up Nginx with Ruby on Rails using Passenger and Ruby Enterprise Edition [...]
[...] the previous article, we set up Nginx with Ruby Enterprise Edition and Passenger support. Now we need to get php running [...]
(unless I’m missing something….)
You’re going to need
passenger_enabled on;
somewhere. I assume it’d be best to set this in the server {} block so you have granular control of which sites need passenger and which don’t. If all sites are using passenger it can be included in the main nginx.conf
Great article though Thanks!
You are correct, Alex. I didn’t really set up a specific site in the article, so I didn’t mention that. I’ve fixed it now. Thanks for the feedback.
Excellent article – had me up and running in minutes. Super big thank you.
Linked back to your blog from here:
http://rubyredbricks.com/2010/4/9/redmine-on-linode-part-1
Had a tiny issue with " and & HTML escape in the nginx script file – minor, but had to do a quick find/replace before saving.
Thanks again – hugely appreciated.
Ah.. hilarious.. your blog swallowed the HTML escapes in my post..