Ruby 1.9.2 on Ubuntu 11.04

May 6, 2011 at 2:03 PM

I've been building an application from scratch, and I want to go with the latest and greatest of the Ruby world. It's not yet clear to me which of Ruby 1.9.2, JRuby, and REE fit the bill, but I've picked 1.9.2. – at least for now.

I'm building around Ubuntu server, and am automating this process with Chef. I've seen two different companies get stuck on outdated Ruby or Rails versions due to lack of easy provisioning, and I don't want to be in that boat. On the other hand, I want to devote as much time as possible to user facing features; no one's going to use what I make based on our future server maintenance paths.

Ubuntu packages

Ubuntu 11.04 provides a fake 1.9.2 package that is provided by ruby1.9.1. Installing ruby1.9.1 actually installs 1.9.2-p0, but all of the binaries are suffixed with 1.9.1. I hate this false naming on a purely conceptual level, but I'm sure there's some Debian-based compatibility issue and I could get over it. However, there have been three important releases since 1.9.2-p0 that contain significant bug fixes. The combination makes that a show stopper for me.

RVM

RVM is a tempting option. It's PATH magic is a little too incomplete for production use, in my opinion – RVM binaries are conspicuously absent for cron jobs and other non-interactive shells. This could probably be fixed, but that would feel like a hack around a hack. And I really don't want to deal with the eventual and inevitable breakage of all that magic in a production environment.

Compile from source

I considered just compiling a binary on each machine, but this is a quick path to upgrade/maintenance hell. Another downside (that RVM shares) is the time cost – with a precompiled package, Ruby is installed in a matter of seconds. Compiling for minutes could be a minor problem when provisioning a bunch of extra instances in The Cloud.

Roll your own .deb

I decided to combine the source option with the packing option. This allows me to quickly distribute and install a binary while retaining control over patch level, executable names, et cetera. However, it made me appreciate the difficulties faced by Ruby package maintainers – it's not exactly a straightforward process.

Here are some things I learned the hard way:

Here's the build process I settled on:

#!/bin/bash
sudo apt-get -y install zlib1g-dev libssl-dev libreadline5-dev
libyaml-dev build-essential bison checkinstall
cd /tmp
wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
tar xvzf ruby-1.9.2-p290.tar.gz
cd ruby-1.9.2-p290
./configure --prefix=/usr\
            --program-suffix=1.9.2\
            --with-ruby-version=1.9.2\
            --disable-install-doc
make
sudo checkinstall -D -y\
                  --fstrans=no\
                  --nodoc\
                  --pkgname='ruby1.9.2'\
                  --pkgversion='1.9.2-p290'\
                  --provides='ruby'\
                  --requires='libc6,libffi5,libgdbm3,libncurses5,libreadline5,openssl,libyaml-0-2,zlib1g'\
                  --maintainer=brendan.ribera@gmail.com
sudo update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.9.2 500\
                        --slave   /usr/bin/ri   ri   /usr/bin/ri1.9.2\
                        --slave   /usr/bin/irb  irb  /usr/bin/irb1.9.2\
                        --slave   /usr/bin/gem  gem  /usr/bin/gem1.9.2\
                        --slave   /usr/bin/erb  erb  /usr/bin/erb1.9.2\
                        --slave   /usr/bin/rdoc rdoc /usr/bin/rdoc1.9.2

I'm not 100% confident in my checkinstall/deb-foo – namely, the semantics of --requires and --provides are a little unclear to me. Nor am I sure that the list of required binaries that I provided is completely accurate. What I do know is that all of this works.

I can now automate installation of this package on any machine I provision and instantly have the latest Ruby patch level with properly named binaries. Cool!

Updated 2011-09-01 15:12 to point this script at the 1.9.2-p290 release.