Setting up a Rails 3 virtual machine using Vagrant and VirtualBox

I recently started bringing other developers on board to help me with a project that up until then I had been the sole developer on. I already had some rudimentary installation instructions that I had updated on occasion as I was originally developing the application, but it turns out that all the developers experienced problems of one kind or another while following along on their own development machines. Although I had recommended using RVM to at least isolate the application gem bundle, it was clear that there were other per-machine libraries and dependencies that were not being accounted for. So, I decided to include instructions on setting up a virtual machine which would hopefully alleviate these issues. My problem with VMs in general though, especially ones that you want to spin up and tear down quickly, is that it’s still possible for everyone involved in the project to be using a different VM manager and linux distro, and thus a different package manager and standard lib setup, and you still need to do a lot of setup after the fact to get all the necessary components to work. Enter Vagrant.

Vagrant is “a tool for building and distributing virtualized development environments.” It’s a command line based utility (Ruby gem) that helps you setup and teardown VMs using Oracle’s VirtualBox virtualizer. And since both Vagrant and VirtualBox work on Linux, Mac OSX and Windows, it’s perfect for distributed development teams.

The following write-up is based on a nearly year-old article by Pete McBreen, but updated for the most recent release of Vagrant. We’re also going to install Imagemagick and the Nokogiri prerequisites. Note that this particular set of instructions doesn’t include the setup of any database other than SQLite (i.e. MySQL or Postgres), but hopefully you can figure that on your own if you need to after following along with the rest of this walk through.

Before beginning make sure you have the most recent version of VirtualBox installed, as well as Ruby and RubyGems.

From the console, run the following commands in the directory where you want your VM to run from:

$ gem install vagrant
$ vagrant box add lucid32 http://files.vagrantup.com/lucid32.box
$ vagrant init

The first command installs the Vagrant gem, which includes the vagrant utility. The second command prepares a new VM based on Ubuntu and downloads the source (if necessary) from the specified URL. The last command generates some files into the current folder that we will use to provision the VM.

Edit the newly generated Vagrantfile file to this:

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant::Config.run do |config|
  config.vm.box = "lucid32"
  config.vm.provision :chef_solo do |chef|
    # Grab the cookbooks from the Vagrant files
    chef.recipe_url = "http://files.vagrantup.com/getting_started/cookbooks.tar.gz"
    # Tell chef what recipe to run. In this case, the `vagrant_main` recipe
    # does all the magic.
    chef.add_recipe("vagrant_main")
  end
  config.vm.forward_port 80, 8080
  config.vm.network :hostonly, "192.168.10.200"
end

This tells vagrant to use the lucid32 VM we just prepared, to include the “solo” recipe from the chef project which will give us some useful webdev tools, to port forward apache’s default port to a higher port, and finally to make the machine accessible on the specified IP address from the host machine. The IP address can be whatever you want it to be, as long as it’s in a different subnet than your host machine.

Save your changes and close the file. Back at the console, run:

$ vagrant up

This starts up the server via VirtualBox. Now log into the VM:

$ vagrant ssh

You won’t need any special username or password to SSH in, nor will you need one for any of the next steps.

Start setting it up. Note that all of these commands will be run inside the VM that we are SSH’d into. Your host machine will be unaffected.

$ sudo apt-get -y install git-core
$ sudo apt-get -y install curl
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
$ source ~/.profile
$ rvm requirements

Look for output from that last command that starts with “# For Ruby / Ruby HEAD (MRI, Rubinius, & REE), install the following:” It will probably look something like this:

$ sudo apt-get install -y build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion

Paste it into your terminal and run it to install any missing dependencies.

Make sure everything is working OK so far with:

$ rvm info

Next, setup Ruby and Bundler on the VM:

$ rvm install 1.9.2
$ rvm use 1.9.2 --default
$ gem update --system
$ gem install bundler

We’re using Nokogiri for parsing some HTML, but there are some prereqs that we’ll need to install before we install the gems that use it (via our gem bundle):

$ sudo apt-get install -y ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8
$ sudo apt-get install -y libreadline-ruby1.8 libruby1.8 libopenssl-ruby
$ sudo apt-get install -y libxslt-dev libxml2-dev

Installing Imagemagick is a bit simpler:

$ sudo apt-get install -y imagemagick

Configure Git and SSH:

$ cd ~/.ssh
$ ssh-keygen -t rsa -C "your.email@address.com"

Note: Use the same email address that you have registered at Github

Now we need to add your SSH key to the Git repository. Run:

$ cat id_rsa.pub

Now copy the output of that to the clipboard, login to your Github account, click the “Account Settings” icon, then the “SSH Keys” link, click “Add New SSH Key”, give it a title and paste your key into the “Key” box, then save it.

Now we will test that it works

$ ssh -T git@github.com

You should see a message like:

Hello, username! You’ve successfully authenticated, but GitHub does not provide shell access.

Now configure Git:

$ git config --global user.name "Your Name"
$ git config --global user.email "your.email@address.com"

The virtual folder /vagrant on the VM is linked to the same folder from which you ran vagrant init and vagrant up. We will place the project files there so we can interact with them in the host system too:

$ cd /vagrant
$ mkdir project
$ cd project
$ git clone ssh://git@github.com/username/your-project.git .

Now edit your database config files as necessary and install the gem bundle:

$ bundle install --without production staging

If that completes w/o error then you can continue with the rest of the configuration process for your application. Once it is setup and your rails server is running, you can access this VM in the browser on your host computer using the URL http://192.168.10.200:3000.

We seem to have a compulsion these days to bury time capsules in order to give those people living in the next century or so some idea of what we are like. I have prepared one of my own. I have placed some rather large samples of dynamite, gunpowder, and nitroglycerin. My time capsule is set to go off in the year 3000. It will show them what we are really like.

— Alfred Hitchcock