Portable Development Environments with Vagrant

Standardize your Local Development Environment to something Lightweight, Reproducible, and Portable

April 28, 2014
Development, Footer

I get excited when a fellow developer asks me how to improve her local development workflow, especially when she is looking to standardize a local development environment across an entire team of programmers. I immediately blurt out, "use Vagrant, it's awesome!" And it is. Trust me.

Old School Development

In the past, it was common to setup a local development stack on your host machine using MAMP (Mac) or WAMP (Windows). MAMP and WAMP are software packages that provide an Apache, MySQL, and PHP installation out-of-the-box. And this approach is OK if you want a quick and dirty local development environment all to yourself.

However, this is not an ideal scenario if, as is considered best practice, you need a local development environment that is close (if not identical) to your production environment. MAMP and WAMP are also not ideal if you need to standardize your local development environment across an entire team of programmers.

What if you need a specific version of PHP that differs from what MAMP provides? What if you want to use nginx instead of Apache? You can see how MAMP and WAMP quickly become problematic.

Use Vagrant to Share Development Environments

Use Vagrant, it's awesome! Vagrant is software to "create and configure lightweight, reproducible, and portable development environments." In layman's terms, Vagrant lets you quickly setup, use, teardown, and rebuild disposable virtual machines for local development. These Vagrant virtual machines are either pre-built or built to your specifications (using Puppet or Chef).

After a Vagrant virtual machine is built, it is super easy to package it up and send to your entire programming team. Each team member may then reproduce the exact same Vagrant virtual macine for her own local development. This lets your team standardize on the exact same server software that closely mimics your eventual production environment. Why is this important? By using a local development environment that is closely aligned with your production environment, you will not have unpleasant surprises when you deploy your code to production; the project code is developed using the same server OS and software as the production server.

Get Started


So how exactly do you get started with Vagrant? First, download and install VirtualBox. Next, download and install Vagrant. Both VirtualBox and Vagrant are free and have simple installers for OS X and Windows.

Use a Pre-Configured Vagrant Box

The easiest way to create a Vagrant virtual machine is using a ready-made Vagrant box. A Vagrant "box" is a template, or starting point, from which you create your own Vagrant virtual machines. You can find ready-to-use Vagrant boxes on Vagrant's website at https://vagrantcloud.com/discover/featured. If you search for "PHP", you'll see there are a multitude of pre-configured boxes ready for you to use.

For kicks, let's use the https://vagrantcloud.com/zloesabo/symfony-server box. Navigate to a new working directory and run this command:

vagrant init zloesabo/symfony-server

This will create a new Vagrant virtual machine, based on the zloesabo/symfony-server Vagrant box, pre-configured with nginx, PHP 5.5, Composer, and MySQL. If you can't find an existing Vagrant box that suits your needs, you can configure your own Vagrant virtual machine with Puppet or Chef.

Create a Custom Vagrant Virtual Machine

You can easily provision a custom Vagrant virtual machine with your own Puppet configuration. Just run vagrant init to create a new file named Vagrantfile, and add this snippet into the Vagrantfile's Vagrant.configure block:

config.vm.provision "puppet" do |puppet|
  puppet.manifests_path = "path/to/manifests"
  puppet.module_path = "path/to/modules"
  puppet.manifest_file  = "site.pp"

Ensure the puppet.manifests_path and puppet.module_path settings point to the appropriate directories, and then run vagrant up. Vagrant will create the new virtual machine and provision it using your Puppet manifest.

If Chef is more to your taste, add this snippet into the Vagrantfile's Vagrant.configure block and change the appropriate settings as needed:

config.vm.provision "chef_solo" do |chef|
  chef.cookbooks_path = "../my-recipes/cookbooks"
  chef.roles_path = "../my-recipes/roles"
  chef.data_bags_path = "../my-recipes/data_bags"
  chef.add_recipe "mysql"
  chef.add_role "web"
  # You may also specify custom JSON attributes:
  chef.json = { :mysql_password => "foo" }

If you are not an expert at writing Puppet or Chef manifests, there are plenty of websites that will generate custom Vagrant provisioning files for you. Puphpet and Vaprobash are great options.

Share Your Vagrant Box

When your Vagrant virtual machine is provisioned, you can package it up as a Vagrant box and share it with your team. Find the name of your Vagrant virtual machine; this is shown in VirtualBox when your virtual machine is running. Next, run vagrant package --base your-virtual-machine-name. This will create a package.box file. Share this package.box file with your team members so they may create their own Vagrant virtual machines based on your custom Vagrant box. If you are feeling generous, create an account on Vagrant Cloud and share your custom box with the Vagrant community.


Josh Lockhart's avatar
Josh Lockhart NMC team member
Hi Dave. If you are relying on a pre-built Vagrant box for a production server, you most certainly should perform your due diligence to avoid any potential security issues. The most secure option would be to write your own Puppet/Chef scripts to provision a custom Vagrant machine exactly to your own specifications. But to answer your question, I would use boxes that are trusted and downloaded by the most community members. Hopefully any security issues and malicious intent can be weeded out by the community.
Dave's avatar
Is any due diligence performed on the cloud hosted boxes? How do we know six months from they won't start acting nefariously?

Leave a comment