Vagrant up your Rails development
We've come a long way with web development technologies. To the point where developing on a virtual machine is now a realistic option as the performance issues that once plagued VMs have all but been eradicated. As the sole VM management tool, Vagrant utilises several virtualisation tools VirtualBox, VMware, etc.) and provides a whole host of benefits. It makes your development environment as close as production as possible and it takes away the excuse of "It works on my computer". If you need to work on different projects, you will appreciate not having your machine messed up by different setups. Here I will show you a simple example of spinning up a Rails project using Vagrant.
Caveat: In the guide we refer to a Host Machine
as your local environment. A Guest Machine
is the virtual machine environment.
1. Create a git repository
Where RAILS_PROJECT
is seen in the instructions below, feel free to replace with a project name of your choice. You don't have to create a Rails project using rails new RAILS_PROJECT
from the beginning, since this will be covered in later section. So in your terminal window:
$ cd RAILS_PROJECT
$ git init
$ echo "Vagrant up your Rails development" > README.md
$ git add .
$ git commit -m "initial commit"
2. Initialise VM box
If you don't have it already installed, download Vagrant and install (see Installation). Do the same with VirtualBox. Next, in your browser, go to https://atlas.hashicorp.com/boxes/search and find the box you need (e.g. Ubuntu, Heroku Ceder, AWS... you name it). Note that all the boxes come with a version so that you can upgrade them when an update is released. Here, I would like to use ubuntu/xenial64
. In a terminal, type:
$ vagrant init --box-version=20170113.0.0 ubuntu/xenial64
This generates a configuration file Vagrantfile
in the project folder with the following content (you'll see a lot of comments generated by Vagrant, but we've kept it short for easier reading):
# -*- mode: ruby -*-
# vi: set ft=ruby :
# ... comments generated by Vagrant
Vagrant.configure("2") do |config|
# ... comments generated by Vagrant
config.vm.box = "ubuntu/xenial64"
config.vm.box_version = "20170113.0.0"
end
To forward my current github SSH key to the VM so that I can seamlessly use git
in the box (especially for bundle installing private gems), I inserted this line into the configuration block:
config.ssh.forward_agent = true
Although Vagrant has a built-in implementation to sync files between host and guest machines (see Vagrant - Synced Folders), its performance is still not the best. The solution is to simply use NFS (suggested in How to make Vagrant performance not suck):
config.vm.synced_folder '.', '/vagrant', type: "nfs"
# this is required if you wish to use NFS under VirtualBox
# @see section Prerequisites in https://www.vagrantup.com/docs/synced-folders/nfs.html
config.vm.network "private_network", ip: "192.168.33.10"
Now your file should look like:
# -*- mode: ruby -*-
# vi: set ft=ruby :
# ... comments generated by Vagrant
Vagrant.configure("2") do |config|
# ... comments generated by Vagrant
config.vm.box = "ubuntu/xenial64"
config.vm.box_version = "20170113.0.0"
config.ssh.forward_agent = true
config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.network "private_network", ip: "192.168.33.10"
end
Now that our box is initialised, we need to create the setup script for Rails. You can use either general shell scripts or whatever makes you look like a hipster (e.g. Chef, Docker and etc.). Since I'm from the ice age, I will just show you the shell scripts.
2.1 Ensure Ubuntu package index is up to date
I'm using Ubuntu for this example so, to make sure I'm using the most current package index, I put these lines into the configuration block of Vagrantfile
:
config.vm.provision "shell", inline: <<-SHELL
apt-get update
SHELL
2.2 Install RVM and Ruby
First we must specify a Ruby version. Create a new file in the main directory for the project called .ruby-version
and put in it the following line:
2.3.3
Then we need to create a folder (vagrant
) and file (vagrant/install_rvm.sh
) to prepare a script for RVM installation (from Using RVM with Vagrant). The contents of the file will be as follows:
#!/usr/bin/env bash
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://get.rvm.io | bash -s $1
Finally, we need to create a file vagrant/install_ruby.sh
to install Ruby with the given version (also from Using RVM with Vagrant):
#!/usr/bin/env bash
source $HOME/.rvm/scripts/rvm || source /etc/profile.d/rvm.sh
rvm use --default --install $1
shift
if (( $# ))
then gem install $@
fi
rvm cleanup all
Now we put them together into our Vagrantfile
, and add the following lines:
# install rvm and ruby
ruby_version = File.read(File.expand_path(".ruby-version", __dir__)).to_s.chomp
config.vm.provision "shell", privileged: false, path: "vagrant/install_rvm.sh", args: "stable"
config.vm.provision "shell", privileged: false, path: "vagrant/install_ruby.sh", args: ruby_version
NOTE: that
privileged: false
is required. Otherwise, the scripts will be run as root.
2.3 Get Rails ready
We still need to initialise a Rails project and install postgresql. First create a new file vagrant/setup.sh
and add the following to it:
#!/usr/bin/env bash
# install javascript runtime, which is required by gem `uglifier`
sudo apt-get install -y nodejs nodejs-legacy npm
# install postgresql
sudo apt-get install -y postgresql postgresql-contrib postgresql-client libpq-dev
# create superuser using current linux user
sudo -u postgres createuser -s -e `whoami`
# gem install
cd /vagrant
gem install bundler --no-ri --no-rdoc
# to check whether Rails has been initialised
# if no, create a Rails project using the folder basename ($1), which is mounted to /vagrant in VM
if [ ! -f Gemfile ]; then
gem install rails --no-ri --no-rdoc
rails new $1 --skip-bundle --no-skip-git --database=postgresql
mv $1/* .
rm -r $1
fi
# all setup in README file could go here
bundle install
bundle exec rake db:create db:migrate db:seed
HINT: If everything is executed in this script, no more setup section should be required in the README
Add this, together with port forwarding configuration, to the Vagrantfile
:
# make sure that the port Rails uses is forwarded to VM
config.vm.network "forwarded_port", guest: 3000, host: 3000
# current working folder basename
base_name = `basename $(pwd)`
config.vm.provision "shell", privileged: false, path: "vagrant/setup.sh", args: base_name
The complete Vagrantfile
should now look like:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.box_version = "20170113.0.0"
config.ssh.forward_agent = true
config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.provision "shell", inline: <<-SHELL
apt-get update
SHELL
# install rvm and ruby
ruby_version = File.read(File.expand_path(".ruby-version", __dir__)).to_s.chomp
config.vm.provision "shell", privileged: false, path: "vagrant/install_rvm.sh", args: "stable"
config.vm.provision "shell", privileged: false, path: "vagrant/install_ruby.sh", args: ruby_version
# this is required if you wish to use NFS under VirtualBox
# @see section Prerequisites in https://www.vagrantup.com/docs/synced-folders/nfs.html
config.vm.network "private_network", ip: "192.168.33.10"
# make sure that the port Rails uses is forwarded to VM
config.vm.network "forwarded_port", guest: 3000, host: 3000
# current working folder basename
base_name = `basename $(pwd)`
config.vm.provision "shell", privileged: false, path: "vagrant/setup.sh", args: base_name
end
Save the Vagrant setup in your terminal window:
$ git add .
$ git commit -m "Getting ready for Vagrant up! "
3. Rails up
Finally, it's time to Rails up! Enter the following commands in your terminal:
$ vagrant up
This is provisioning and bringing up the box, so it may be a long wait. When it's done then run:
$ vagrant ssh
You should now see your terminal has sshed into the box:
ubuntu@ubuntu-xenial:~$
Go to the default working directory in your new Guest Machine:
$ cd /vagrant
Start Rails server and allow connections from outside of guest machine, since default domain localhost
will restrict connections within guest machine.
$ rails s -b 0.0.0.0
Then open http://localhost:3000 as usual to start fancy development with Rails!
You can continue from hereon with your regular development and be able to view the changes you make through the browser.
Closing down
When you're ready, you can shut down by holding down CTRL
+ C
in the terminal window to terminate the Rails server. And then type:
$ exit
You should now have exited the ssh
and you can shut down your new VM with the following command:
$ vagrant halt
Bonus
It would be even better if you could create shortcut functions to send commands over SSH to guest machine. Add these lines at the end of your shell startup file, e.g. ~/.profile
or ~/.bashrc
.:
v () {
command="cd /vagrant; $@"
vagrant ssh -c $command
}
vb () {
command="cd /vagrant; bundle exec $@"
vagrant ssh -c $command
}
Firstly, from your Host Machine (i.e. yourusername$
not ubuntu@ubuntu-xenial:~$
), reload your shell startup file:
$ source ~/.profile
Then you could run:
$ v rails s -b 0.0.0.0
or
$ v rake spec
In this way, you don't need to repeat yourself typing vagrant ssh
then cd /vagrant
in order to run a command under the working directory in the guest machine. You will still be able to debug your Rails app at breakpoints you've placed in both Rails console/server and rspec/unittest suite, just as you would do on your local machine.
Finish
Don't forget to save what we have in local machine terminal:
$ git add .
$ git commit -m "Ready for Rails up!"
Happy programming! Fin.
Latest Articles by Our Team
Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.
-
No app left behind: Upgrade your application to Ruby 3.0 and s...
-
A look forward from 2020
-
Testing Rails applications on real mobile devices (both design...
We Hire Only the Best
reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.
We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.
Free Community Workshops
We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.