Introduction to Vagrant

Vagrant is a tool to create and configure VMs for development. You basically write a config file that can be shared with the rest of the team and added to your project repository.

It works with different providers such as VirtualBox or VMWare. This post is an introduction to the configuration and will show you how to quickly setup an Ubuntu box for RVM+Ruby development and another for Apache+PHP.

Table of Contents

Installation

First you need to install Vagrant and whatever Virtualization software you prefer; I choose VirtualBox but it doesn't make much of a difference.

Both packages are very easy to install, no matter if you are a Linux, Mac or Windows user; they have click-next-to-install packages for you.

  1. Virtual Box Website
  2. Vagrant Download

Just follow the installation guide for your platform and then open a terminal to make sure you have the 'vagrant' command.

Command line

There are many commands you can use but we are going to focus on "vagrant up", "vagrant halt" and "vagrant ssh".

The first one will bring up the development/virtual machine based on what we will put in the configuration file; the second will shut it down, and the third one will allow us to login onto our virtual machine.

As a side note make sure you add "/.vagrant/" to your project .gitignore

Boxes

The concept of boxes is important to understand; these reefer to virtual machine "images"; or S.O. (but not only limits to that), these are used to create the virtual environment with some tweaks.

In the examples I will be using "ubuntu/xenial64"; for this we only need to type the name on the config file and vagrant will automatically download the necessary files upon creation; what you pick depends on the environment you want to recreate and work with. 

View a complete list of available boxes

Vagrant UP / configuration

Usually you are going to run "vagrant up" on your project root path; also here is where we are going to save our required configuration file which by default is named "Vagrantfile" (without any extension).

We write the Config using Ruby syntax, but do not worry if you don't know the language; the config is very simple and pretty straight forward. Bellow is a basic one, the details about each sections are explained in the comments within the code.

Provisioning

Provisioning is the way you customize your box, this can be done by providing a set of SHELL commands, these are executed when the VM is created.

There are two ways of doing this: INLINE and in FILES, where we can just include the commands in a specific section of the Vagrantfile or we can also specify an external Bash file path to load. The last one is very useful if your config file starts to grow.

Also, provisioning is a very large topic and depends a lot of what you are doing; what S.O. you are using and much more. On this introduction post I'll focus on Linux boxes and SHELL provisioning.

# Configuration file version
Vagrant.configure(2) do |config|

  # Box name, for a complete list visit:
  # http://atlas.hashicorp.com/boxes/search
  config.vm.box = "ubuntu/xenial64"

  # This isnt required, but for some projects I needed to bump the memory of my
  # the virtual machine thats going to be created.
  config.vm.provider "virtualbox" do |v|
    v.memory = 1024
  end

  # Simple rooting config. This allows you for example to type
  # http://localhost:8888 in your browser and get whatever
  # service is running in your virtual machine's 80
  config.vm.network "forwarded_port", guest: 80, host: 8888

  # (Carefull here). This line allows the VM to work just like any other
  # computer in you network; maybe usefull when you want to share or just
  # connect 2 VMs.
  #config.vm.network "private_network", ip: "192.168.33.10"

  # This one is specific for Virtualbox, allows your to have
  # network/internet access in the virtualmachine. Maybe you are writing
  # an app that needs to connect to some external API service like
  # Twitter API
  config.vm.provider "virtualbox" do |v|
    v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
    v.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
  end

  # Provisioning method (1): Inline
  config.vm.provision "shell", inline: <<-SHELL
    apt-get -y update

    # Add more commands here....
  SHELL

  # Provisioning method (2): You must create a file
  # named provisionfile.sh next to your Vagrantfile
  #config.vm.provision "shell", path: "provisionfile.sh"
end

SSH and local files

So, you just created the config file(s) next step is to run "vagrant up". If this is the first time it may take some time, it may download stuff... so be patient, you'll get a many console messages but as long none of them are errors you are good to go.

Next is "vagrant ssh"; this logs you in into your the new virtual machine command prompt. But what about your projects files, and how are these shared with the virtual environment?

By default, the folder where you created the Vagrantfile (on YOUR computer) is the folder that is shared with the VM, so if you have something like this:

daniel-air:test daniel$ ls 
.gitignore index.php Vagrantfile vendor

Then on the VM the files are shared in the /vagrant folder. Following the previous example you get something like this:

daniel-air:test daniel$ vagrant ssh
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-91-generic x86_64)
vagrant@vagrant-ubuntu-trusty-64:~$ cd /vagrant
vagrant@vagrant-ubuntu-trusty-64:~$ ls
.gitignore index.php Vagrantfile vendor

And yes!, there are many options to change the mount point, adding multiple folders, etc.

RVM + Ruby provision file

Simple provision to include in the project to setup a Ruby dev environment.

Download base project here

#!/bin/bash

RUBY_VERSION="2.2.2"

apt-get update

apt-get -y install git nodejs curl git curl unzip

# Install rvm
if ! type rvm >/dev/null 2>&1; then
  curl -sSL https://rvm.io/mpapis.asc | gpg --import -
  curl -L https://get.rvm.io | bash -s stable
  source /etc/profile.d/rvm.sh

  # Add vagrant's users to rvm group
  usermod -a -G rvm vagrant
  usermod -a -G rvm ubuntu
fi

# Install ruby
if ! rvm list rubies ruby | grep ruby-${RUBY_VERSION}; then
  rvm install ${RUBY_VERSION}
fi

# Set our Ruby version
rvm --default use ${RUBY_VERSION}

# Install our default global gems
gem install bundler

# Remove unnecessary stuff
apt-get -y autoremove

#
# Add more here ... !
#

Apache + PHP provision file

This is also a very simple setup, it assumes you have a {projectpath}/public directory in YOUR PC (next to your Vagrantfile).

This one is a bit longer but the "trick" here is that it creates a new Apache "virtual host" and then we set the DocumentRoot to /vagrant/public. It also installs composer.

Download base project here. (also includes MySQL and phpMyAdmin)

#!/bin/bash

# Some vars
apache_config_file="/etc/apache2/envvars"
apache_vhost_file="/etc/apache2/sites-available/vagrant_vhost.conf"

# This is the public folder of your project, where something like index.php is.
project_web_root="/vagrant/app/public"

apt-get update

# Some utilities i like to have
apt-get -y install git curl unzip

# Installing Apache
apt-get -y install apache2

# Create our new virtual host
if [ ! -f "${apache_vhost_file}" ]; then
  cat << EOF > ${apache_vhost_file}
ServerAdmin webmaster@localhost
DocumentRoot ${project_web_root}
LogLevel debug 
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined 

    AllowOverride All
    Require all granted

EOF

# Disable default "hello world" site, and enable ours
a2dissite 000-default
a2ensite vagrant_vhost

# PHP 7; also Curl and Cli are required by composer
apt-get -y install php php-curl php-cli libapache2-mod-php

# Some other packages
apt-get -y install php-mcrypt php-mbstring php-intl

# Install latest version of Composer globally
if [ ! -f "/usr/local/bin/composer" ]; then
  curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
fi

# restart apache
service apache2 restart

# Remove unnecessary stuff
apt-get -y autoremove
About
Related Posts
  • Fancy words in Tech Episode II: GraphQL

    It's been around for many years, and like other buzz-words many companies choose the tech just because "certain FANG company uses", then It must be good for my solution. Here i will try to summarize the most important key points of this technology, when and where is intended to be used and what a developer does when working on a project like this.

  • Using Makefiles to improve Docker image build experience

    Makefile is a building tool that's been around forever; and while some of us may remember it from building our first couple projects (and may hate those times and the struggle); But I believe it's an awesome tool that by just adding a single file to our project It can speed / easy up our daily work flow on: how we build, run locally, etc our 'Dockerized' projects

  • The SOLID Programming Principles OOP(s)!

    We can think of these as a general guide. There are many more, here are the ones I come up often, they are five and go by the acronym of S.O.L.I.D. The good thing about SOLID is that helps you decouple/breaking apart your code. Giving our modules independence of each other and make our code more maintainable, scalable, reusable and testable.

Comments
The comments are closed on this section.
Hire me!

I'm currently open for new projects or join pretty much any project i may fit in, let me know!

Read about what I do, or contact me for details.