I recently spent time developing a toy Rails 5 app using a Vagrant box. One of my goals is to avoid updating Homebrew. I experienced issues after updates, and had to spend evenings fixing package issues and OpenSSL problems.

I used the rails-dev-box VM created by members of the Rails team. Although the project’s README explicitly says that the VM is meant for Rails core development, it comes with MySQL, PostgreSQL, and Ruby 2.3. In addition, Apache is already installed on the guest OS (Ubuntu), which is a bonus because I can simulate deploying to, and running on, a production environment.

Developing in the VM

Following the setup instructions on the rails-dev-box Github page, I accessed the VM using vagrant ssh. I proceeded to create a Rails 5 app on /vagrant, which is mapped to the rails-dev-box directory on the host machine.

I needed to use bin/rails server -b 0.0.0.0 before I could browse to http://localhost:3000 on my Mac’s Chrome and Firefox browsers. Specifying 0.0.0.0 allows the VM to bind to every available network interface. The Vagrantfile file on the rails-dev-box directory contains the network configuration for the VM. It specifies that port 3000 is forwarded to the guest OS.

I was able to edit my files in either the host or guest machine, although adding or removing files from the Mac resulted in .DS_Store files being created. Pushing and pulling from Github worked in either OS.

Creating a private network

To simulate deploying the app using Capistrano, I created a private network using two rails-dev-box VMs. I cloned the rails-dev-box Github project to another directory on the Mac, and modified the new Vagrantfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 # -*- mode: ruby -*-
 # vi: set ft=ruby :
 Vagrant.configure('2') do |config|
   config.vm.box      = 'ubuntu/yakkety64' # 16.10
   config.vm.hostname = 'rails-dev-box-deploy'
 
   config.vm.network "private_network", type: "dhcp"
   config.vm.network :forwarded_port, guest: 3030, host: 3030
 
   config.vm.provision :shell, path: 'bootstrap.sh', keep_color: true
 
   config.vm.provider 'virtualbox' do |v|
     v.memory = 2048
     v.cpus = 2
   end
 end

I changed the hostname (line 5), used DHCP to assign the IP address (line 7), and also changed the forwarded port (line 8). I used port 3030 instead so I can test this new VM in isolation. On the first VM, I also changed the configuration and assigned this VM an IP from DHCP as well.

On rails-dev-box-deploy, I created a git repo for Capistrano to use. I installed the text-only browser Lynx so I can troubleshoot Apache locally.

The Vagrant website contains an example of controlling multiple machines with one Vagrantfile, and I’ll try this configuration on another development project.

Observations

The most time-consuming part was the initial VM setup, after issuing the command vagrant up for the first time. The file bootstrap.sh on the rails-dev-box directory determines what software will be downloaded and configured. After this, installing other gems and packages was a breeze and the whole process felt like developing on my local machine. I am also comfortable enough with Vim that I didn’t need the graphical interface that Ubuntu is known for. More importantly, I could keep my Mac’s environment clean and avoid updating Homebrew.