How to host a Rails app with Phusion Passenger for Nginx

Handwritten by TVD


I believe Phusion Passenger for Nginx will do for Rails Deployment what jQuery did for JavaScript Development. So it should come as no surprise that this will be an opinionated Rails deployment tutorial. Simply put, I couldn't phantom deploying Rails without Passenger for Nginx.

Today I'm going to run you through getting your Rails app running on Ubuntu, Ruby Enterprise Edition (REE), Rails, Nginx and Phusion Passenger for Nginx. Lastly, I'll quickly show you how to successfully deploy your Rails app to a sub URI without any 403 Forbidden errors.

Here are my notes from one of my client's latest Rails deployment.

Ruby Enterprise Edition (REE):

We're going to start by installing Ruby Enterprise Edition (REE). Download the latest .deb REE package, then install it:


sudo dpkg -i ruby-enterprise_1.8.7-2010.02_i386_ubuntu10.04.deb

ruby -v

You should see something similar to ruby 1.8.7 (2010-04-19 patchlevel 253) ... Ruby Enterprise Edition 2010.02. Now, update your RubyGem package manager and all of your installed gems:

sudo gem update --system
sudo gem update

Ruby on Rails

At this point you should make sure you've installed the Ruby on Rails gem. Don't worry, you've probably already done that. Here's the command to install Rails (just in case):

sudo gem install rails
rails -v

Install, Configure and Manage Nginx

Install Nginx

First, let's install the Open SSL library. You're going to need this later for SSL support and management:

sudo aptitude install libssl-dev

Next, we are going to install the Passenger for Nginx module. This module will install both Nginx and Passenger:

sudo passenger-install-nginx-module

Follow the default options. Soon, you'll be prompted with two options to either select 1 or to select 2.

Choose option 2 if you need to install additional Nginx modules. One module that comes to mind is the Nginx SSL module.

For this tutorial, select option 1. Let the install finish. Congrats, you've just installed a blazing fast Webserver (Nginx) and Rails application server (Passenger)!

You will also need to create a user and group for nginx. Issue the following command to do so:

adduser --system --no-create-home --disabled-login --disabled-password --group nginx

Finally, let's create an init.d script and have it boot at startup. The init.d will allow us to control Nginx:

sudo nano /etc/init.d/nginx

Copy and paste the following Nginx init script into the new file:

#! /bin/sh

  # 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


  test -x $DAEMON || exit 0

  # Include nginx defaults if available
  if [ -f /etc/default/nginx ] ; then
      . /etc/default/nginx

  set -e

  . /lib/lsb/init-functions

  case "$1" in
      echo -n "Starting $DESC: "
      start-stop-daemon --start --quiet --pidfile /opt/nginx/logs/$ \
          --exec $DAEMON -- $DAEMON_OPTS || true
      echo "$NAME."
      echo -n "Stopping $DESC: "
      start-stop-daemon --stop --quiet --pidfile /opt/nginx/logs/$ \
          --exec $DAEMON || true
      echo "$NAME."
      echo -n "Restarting $DESC: "
      start-stop-daemon --stop --quiet --pidfile \
          /opt/nginx/logs/$ --exec $DAEMON || true
      sleep 1
      start-stop-daemon --start --quiet --pidfile \
          /opt/nginx/logs/$ --exec $DAEMON -- $DAEMON_OPTS || true
      echo "$NAME."
        echo -n "Reloading $DESC configuration: "
        start-stop-daemon --stop --signal HUP --quiet --pidfile /opt/nginx/logs/$ \
            --exec $DAEMON || true
        echo "$NAME."
        status_of_proc -p /opt/nginx/logs/$ "$DAEMON" nginx && exit 0 || exit $?
      echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
      exit 1

  exit 0

To save the file using nano, press ctrl+o, then enter. Then exit by pressing ctrl+x.

Change permission on the script to make it an executable:

sudo chmod +x /etc/init.d/nginx

Have the new executable run at startup:

sudo /usr/sbin/update-rc.d -f nginx defaults

Now, you have the power to start, stop and restart Nginx. Start your shiny new Nginx Webserver with this command:

sudo /etc/init.d/nginx start

Navigate to your server's IP address using Firefox or your favorite browser. You should see "Welcome to Nginx!" This means Nginx is up-and-running. Now we can focus on configuring Nginx for your Rails web application.

Configure Nginx

Edit your Nginx configuration:

sudo nano /opt/nginx/conf/nginx.conf

Make sure Nginx knows the location of your passenger and ruby installation:

. . .
http {
    passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.15;
    passenger_ruby /usr/local/bin/ruby;
. . .
    server {
    . . .

For fun, let's modify our Server section to deploy our Rails app to a Sub URI:

server {
        listen 80;
        charset utf-8;
        root /www/;
        passenger_enabled on;
        passenger_base_uri /blog;
        rails_spawn_method smart;
        rails_env production;

To do this, we have to make a symlink from our Rails app's public directory to the document root of our static website:

ln -s /www/ /www/

This command will create a symlink called blog in the document root /www/

Remember, if you want to make the sub uri work, do not create a folder called blog in the document root. This will get you a nice Rails sub uri 403 Forbidden error from your passenger Nginx setup.

For a typical Xen VPS setup, you should also think about adding the following tweaks to your Nginx conf:

user                      nginx nginx;
worker_processes          4;
worker_connections        1024;
passenger_max_pool_size   6;

Read more about the the passenger_max_pool_size directive. The maximum value depends on your server's cpu processor and other factors. Do experiment!

When you're finished, save the file and restart Nginx:

sudo /etc/init.d/nginx restart

Manage Nginx

In the future you can restart the entire Nginx server or only restart your application with the following command:

touch /www/

The next time you load your Rails app it will restart.

Passenger also has some pretty cool built-in monitoring applications. You can access them using these commands:

sudo passenger-status
sudo passenger-memory-stats

I suggest installing another utility to see what's using memory on your entire server. It's called htop:

sudo apt-get install htop
sudo htop

Well, you're done really! I hope this helps.

For the uninitiated, deploying to Ubuntu (or any Linux distro) can be daunting. But, once you get over having nothing but a black screen to work with, you'll realize how unshackled and productive you feel. Good luck Beloved!

discuss on twitter

every day thousands of developers use our charts & gauges to get the job done right

JavaScript Charts JavaScript Gauges JavaScript Flight Gauges

← return to all articles