Running Ruby on Rails on Nginx

3 minute read

If you want to set up Ruby on Rails on Ubuntu Lucid from scratch, there are quite some articles online to choose from. I found most of them involve compiling, only highlight 1 aspect, or are a bit outdated.

On top of that, getting it right can be hard as there are a number of issues related to Ruby and Debian/Ubuntu.

This is an attempt to put all the sweet info in 1 place.

Ruby

$ export PATH="${PATH}:/var/lib/gems/1.8/bin/"
$ echo 'export PATH="${PATH}:/var/lib/gems/1.8/bin/"' >> /etc/bash.bashrc
$ aptitude install ruby rubygems vim-ruby ruby-dev libzlib-ruby \
libyaml-ruby libreadline-ruby libncurses-ruby rdoc ri libcurses-ruby \
libruby libruby-extras libfcgi-ruby build-essential libopenssl-ruby \
libdbm-ruby libdbi-ruby libxml-ruby libxml2-dev

Rails

Simple:

$ gem install -v=2.3.5 rails

gem install rails should have worked but 2.3.6 - 2.3.8 (current at the of writing) have issues with mongrel

Or, if you want to live on the edge and try the latest:

$ gem install rails --pre

Or With RVM

RVM is a command line tool which allows us to easily install, manage and work with multiple ruby environments from interpreters to sets of gems. See installation instructions and a full tutorial on that.

App

My new app is called myapp.example.com

$ cd /var/www
$ rails new myapp.example.com
$ cd myapp.example.com

Have a look around and see what you can find .

Thin

Thin will be the Ruby server

$ gem install thin
$ thin install
$ /usr/sbin/update-rc.d -f thin defaults
$ thin config -C /etc/thin/myapp.example.com -c /var/www/myapp.example.com --servers 3 -e development # or: -e production for caching, etc

Or Mongrels

If you don't like Thin..

$ aptitude install mongrel mongrel-cluster
mongrel_rails cluster::configure -e development -p 3000 -N 3 -c /var/www/myapp.example.com -a 127.0.0.1 # or: -e production for caching, etc
$ mkdir /etc/mongrel_cluster
$ sudo ln -nfs /var/www/myapp.example.com/config/mongrel_cluster.yml /etc/mongrel_cluster/myapp.example.com.yml
$ #sudo ln -nfs /var/www/myapp.example.com/config/mongrel_cluster.yml /etc/mongrel-cluster/sites-enabled/myapp.example.com.yml

Nginx

Nginx will be the Web server, proxing ruby requests to thin, running on ports 3000-3002 If you haven't installed it yet, do

$ aptitude install nginx

Now that you have Nginx, create a vhost. Edit /etc/nginx/sites-available/myapp.example.com and type:

upstream myapp {
  server 127.0.0.1:3000;
  server 127.0.0.1:3001;
  server 127.0.0.1:3002;
}
server {
  listen   80;
  server_name .example.com;

  access_log /var/www/myapp.example.com/log/access.log;
  error_log  /var/www/myapp.example.com/log/error.log;
  root     /var/www/myapp.example.com;
  index    index.html;

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  Host $http_host;
    proxy_redirect  off;
    try_files /system/maintenance.html $uri $uri/index.html $uri.html @ruby;
  }

  location @ruby {
    proxy_pass http://myapp;
  }
}

Then make it available to the public

$ ln -nfs /etc/nginx/sites-available/myapp.example.com /etc/nginx/sites-enabled/myapp.example.com

Databases

First set up SQLite

$ aptitude install -y libdbd-sqlite3-ruby sqlite3 libsqlite3-dev libsqlite3-ruby
gem install sqlite3-ruby

MySQL?

Optionally if you want to use MySQL install the following (but do sqlite anyway):

$ aptitude install -y libmysqlclient-dev
$ gem install mysql

Then change your /var/www/myapp.example.com/config/database.yml and make it say something along the lines of

development:
  adapter: mysql
  host: localhost
  database: myapp
  username: myapp
  password: xxxxxxx

Note! database.yml doesn't accept tabs. If you are in vim, you might need to do:

:set expandtab
#:set tabstop=4 # how many spaces should tabs be replaced withs
:retab

Also, make you app require the mysql gem by adding the following to ./Gemfile

gem 'mysql', '2.8.1'

I am assuming you already have a mysql-server running. If not, you also need to aptitude install mysql-server first.

Nice Gems

$ gem install \
 uuidtool \
 ruby-debug \
 ruby-graphviz \
 json \
 activemerchant

Bring App Live

Let's restart our daemons to see if it worked:

For Thin:

$ /etc/init.d/thin restart && /etc/init.d/nginx reload; tail -f log/*.log

For Mongrel:

$ mongrel_cluster_ctl restart && /etc/init.d/nginx reload; tail -f log/*.log

Add this line to above the 2 default routes in config/routes.rb:

# Rails 2
map.root :controller => "home"
# Rails 3
#root :controller => "home#index"

Create a home controller, add a view for it, and remove the 'Welcome aboard' html.

$ script/generate controller home index
$ rm public/index.html
$ echo '<h1>HeyO!</h1><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/9X2u2cdvJSg?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/9X2u2cdvJSg?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object>' > app/views/home/index.erb

If you don't get any errors, point your browser to the Vhost you created, and you should see a pleasant surprise.

Our work is done here.

New to Ruby?

Here's some resources to help you further:

If you think I missed something, please do leave a comment and help me improve this article.

Leave a Comment Right Here