Dec 25, 2010

Install Ruby on Rails on Ubuntu Maverick Meerkat 10.10

If you're running Ubuntu 9.10 and want to install Ruby on Rails I've put together a quick tutorial for you. Not tremendously much has changed since the last tutorial for Jaunty Jackalope. Unicorn is out and while I think it's nifty, I'm going to wait a little while before playing with it. For now my money is still on Phusion Passenger as being the right tool for the job. If all that seems fine, let's get to the details.

Step 1: As usual, the first thing we'll want to do is make sure your version of Ubuntu is up to date.:
sudo apt-get update
sudo apt-get dist-upgrade

Step 2: We'll be installing some software that needs to be built so we'll need to get packages required for compiling. With Ubuntu, you can type this single command and get everything you need:
sudo apt-get install build-essential
sudo apt-get install git-core

Step 3: Once we've got the tools we need it's time to install Ruby. Unlike previous iterations of these instructions we'll be using RVM instead. Why? The default version of Ruby that's shipping in most linux distros is still rather old. If you're running with Rails 3 and Ruby 1.9.2 then RVM is the way to go. We'll pretty much follow the instructions on their website for a systemwide install. We do this so later on our deploy user can enjoy the benefits as well.
bash < <( curl -L http://bit.ly/rvm-install-system-wide )

Whichever user you are logged in as now needs to have the following line at the bottom of your bash profile. Since we installed as root we need to modify it slightly. So open up the .bashrc file of your user and put this at the bottom:

[[ -s "/usr/local/rvm/scripts/rvm" ]] && . "/usr/local/rvm/scripts/rvm"

Next, log out of your system and log back in. Hopefully you saw no errors and the rvm command is now available to you. To test it out enter this in the command line:
type rvm | head -1

The output should say: rvm is a function. If it does, congratulations! We're almost there. Let's go ahead and compile Ruby 1.9.2 using RVM now (warning, this takes a while):
sudo rvm package install zlib
sudo rvm install 1.9.2
sudo rvm use 1.9.2 --default

Now check it out:
ruby -v
==> ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]

If you run into a problem, you'll again want to double check that you've added the line into your ~/.bashrc file. If you've switched users or added a user, it'll need to be added to their ~/.bashrc file as well. That's important to remember if you add a deploy user after this install. You can also check out the troubleshooting section on the RVM Website

Step 4: Now it's time to install MySQL. Do so with the following command:
sudo apt-get install mysql-server libmysql-ruby libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysql-ruby libmysql-ruby1.8 libmysqlclient16 libnet-daemon-perl libplrpc-perl libreadline5 libruby1.8 mysql-client-5.1 mysql-client-core-5.1 mysql-common mysql-server mysql-server-5.1 mysql-server-core-5.1 psmisc libc6 libpcre3 libpcre3-dev libpcrecpp0 libssl0.9.8 libssl-dev zlib1g zlib1g-dev lsb-base

Be sure to enter (and remember) a root password for MySQL!

Step 5: Install Rails! RVM gives us a bunch of advantages and one of them is being able to isolate gems. I'm not going to do that here but there's a nice post that can guide you through it if you're interested.
rvmsudo gem install rails --no-rdoc --no-ri

Congratulations, if you're just doing local development then you are done! You probably want to install additional gems specific to your app though. However, if you want to deploy Ruby on Rails onto a server then it's time to setup Nginx and Phusion.


Step 6: We're going to create a directory for your application. In anticipation of Capistrano, let's put it in /var/www/myapp/current. Swap out the myapp with anything you like.
sudo mkdir -p /var/www/myapp/current

If you've got an existing Rails application, it doesn't hurt to populate that directory now. Just make sure that the root to the public directory is /var/www/myapp/current/public. Don't forget to chown it for www-data:
sudo chown -R www-data:www-data /var/www/myapp/current/


Step 7: Now it's time to install Phusion Passenger 3 and let it do it's magic.
sudo apt-get install libcurl4-openssl-dev
rvmsudo gem install passenger --no-rdoc --no-ri
rvmsudo passenger-install-nginx-module

Select option 1 when prompted and let Phusion Passenger do all the heavy lifting for you. The default locations (/opt/nginx) are fine choices too.

At this point you'll be greeted with two options. The first will allow Passenger to do all the work while the second, for advanced users, allows you to point Phusion to your pre-installed Nginx. We're going to make life easy on ourselves and choose option 1. I'd also recommend keeping the default path (/opt/nginx).

The Nginx configuration file (nginx.conf) file is in /opt/nginx/conf/ They've done you the favor of adding the lines you need to get going. Here's what your server block might look like for a basic application:
server {
        listen       80;
        server_name  localhost;
        rails_env production;
        root /var/www/myapp/current/public;
        passenger_enabled on;
        index index.html index.htm;
        client_max_body_size 50M;

        if (-f $document_root/system/maintenance.html) {
          rewrite ^(.*)$ /system/maintenance.html break;
        }
     }


Step 8: Time to make some Nginx tweaks for Ubuntu/Debian. If you're used to running nginx as installed by Debian or Ubuntu then you might notice that you've lost the familiar way to start and stop nginx. Gone is /etc/init.d/nginx stop and /etc/init.d/nginx/start. To get it back, copy (or download) this into a file called nginx in /etc/init.d/ (as root)
#! /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=/opt/nginx/sbin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/opt/nginx/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

case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /opt/nginx/logs/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /opt/nginx/logs/$NAME.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/opt/nginx/logs/$NAME.pid --exec $DAEMON
sleep 1
start-stop-daemon --start --quiet --pidfile \
/opt/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile     /opt/nginx/logs/$NAME.pid \
--exec $DAEMON 
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
exit 1   
;;
esac

exit 0

Next, let's set the permissions and make nginx load on a reboot:
sudo chown root:root /etc/init.d/nginx
sudo chmod +x /etc/init.d/nginx
sudo /usr/sbin/update-rc.d -f nginx defaults

Now you should be able to start and stop nginx using the command you're used to:
sudo /etc/init.d/nginx start


Bonus steps In case it's not already installed, let's grab the perquisites and then install the mysql gem. This will improve performance on your webserver:
sudo apt-get install libmysqlclient-dev
rvmsudo gem install mysql2 --no-rdoc --no-ri

You should also look into using a helper for deployment. I still use Capistrano but there are alternatives such as Vlad the Deployer, Puppet and others. I will also recommend that if you go with Capistrano that you check out the capistrano-ext gem which allows you to do multi-stage deployments.


Troubleshooting If things didn't go smoothly, here are some things to check:

1. There's an error log for nginx in /opt/nginx/logs/ Try looking to see if you get any hints there.

2. If you see a 403 forbidden error, make sure you have permissions set correctly. I'm running Nginx as www-data and I've set the group/user owners of my rails app to match using the chown -R www-data:www-data command. It doesn't hurt to confirm it.

3. Try running your rails app in development mode using the standard rails server. If it doesn't work there then it obviously won't work in production mode either. You may need to do a bundle install (rvmsudo bundle install) or get additional packages for gems such as nokogiri (sudo apt-get install libxml2-dev libxslt-dev)


For help, you should check out the great railsforum or Mailing list front-end. Econify is also available for paid consulting.

2 comments:

  1. Thanks for the fantastic guide- your instructions on 9.10 got me up and running last year, and this one was just in time for me to create a new slice with Maverick. I just had to change one thing to get it to work, from:
    sudo rvm install 1.9.2
    to:
    sudo rvm install 1.9.2 -C --with-zlib-dir=$rvm_path/usr

    ReplyDelete
  2. RVM creators advise not to use 'sudo' when installing any gems, the same is for Ruby versions; So why do you do that in your tutorial, please?

    ReplyDelete