If you never heard about Vagrant, this is the right moment to get acquainted to it. Vagrant is getting very popular amongst open source projects, because it provides a portable and reproducible development environment using virtual machines.
You will never be hostage of the "works on my machine" statement again; the environment is exactly the same for all the developers, regardless of the operational system running as the host machine (although everything can get messy with Windows).
First of all, how it works? If a repository is "vagrant-ready", you will just run a vagrant up in the repository root (after cloning it), and vagrant will provide you with a virtual machine ready to run the project, which you will access directly through your browser. Even the database can be created and populated, as well as other activities such as running composer and installing specific packages, amongst a million other possibilities. This is actually not done directly by vagrant - it's done through provisioners. You will learn more about this in the second part of this post. It's really handy for developers and I can see, in a nearby future - with some improvements -, as a really straightforward way to deliver open source projects to final users as well. Just remembering, Vagrant is open source.
In order to get started, the first thing you need to do is install Vagrant and Virtualbox. Virtualbox is the default Vagrant provider, we will talk about this in a few moments.
Update for Ubuntu users: in the first version of this article, I pointed Ubuntu users to install Vagrant through apt-get, which would install also Virtualbox as a dependency. Unfortunately, the vagrant version available as an apt-get package is outdated (at least in Ubuntu 12.04) and incompatible with this guide, so you better get both packages from their respective websites.
Go to the vagrant downloads page and get it's newest version, then install it. Go to the Virtualbox downloads page and get the appropriate version, then install it. Usually, the newest version of VirtualBox will work just fine, but the safest thing to do is to check which version is currently compatible with Vagrant, by checking the official Vagrant docs.
Some concepts must be cleared before we run our first vagrant box:
A box is basically a package containing a representation of a virtual machine running a specific operating system, for a specific Provider.
The Provider is the piece of software responsible for creating and managing the virtual machines used by Vagrant. The main providers are virtualbox and vmware, but the default one is VirtualBox, since it's free and open source. As you may already know, vmware is not free, so if you want to use vmware with Vagrant you need to purchase a license for vmware-fusion AND a license for the Vagrant vmware plugin. You can find more details about using vmware as a provider here. Lets focus on Virtualbox, since it's the default.
Some people may get confused by the terms Provider and Provisioner. Well, the provider is responsible for providing the virtual machine itself (virtualbox or vmware), and the provisioner will do some task(s) using the vm instance already provided. The provisioners are used to set up the virtual server, installing all necessary software and executing different tasks. The most used provisioners are: Puppet, Chef and Ansible. Shell Script is also a very common option. You can find more information about vagrant provisioners here.
The basic vagrant configuration is based in one file, the Vagrantfile. It shall be placed in your repository root. In this file you will define which base box you want - a box is, basically, a package with an operational system to be run in your virtual machine. Lets see how the Vagrantfile looks like:
Vagrant.configure("2") do |config| config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" config.vm.network :private_network, ip: "192.168.33.101" config.vm.synced_folder "./", "/vagrant" end
Note: With Vagrant 1.5 and the Vagrant Cloud, we only need to provide the config.vm.box option, specifying the box identifier (similar to a repository).
We basically said that we want to use a Precise 64 box (Ubuntu 12.04), defining its IP and a shared folder between our host machine (the base OS where you are going to run vagrant) and the guest machine (the virtual machine itself). This way we can share the same project folder, and you will be able to access your files from inside the VM and get any modifications in real time (its not a copy). For more information about all the available options for the Vagrantfile, take a look at the vagrant official docs.
Place the Vagrantfile in the root folder of your project, then run vagrant up . The first time you run vagrant up, it will need to download the box, so it will take a while. After that, its not going to take more than a few minutes, depending on the amount of tasks you define through provisioners. You shall get an output like this:
➜ vagrant-lab git:(master) ✗ vagrant up Bringing machine 'default' up with 'virtualbox' provider... [default] Clearing any previously set forwarded ports... [default] Fixed port collision for 22 => 2222. Now on port 2200. [default] Creating shared folders metadata... [default] Clearing any previously set network interfaces... [default] Preparing network interfaces based on configuration... [default] Forwarding ports... [default] -- 22 => 2200 (adapter 1) [default] Booting VM... GuestAdditions 4.2.18 running --- OK. [default] Waiting for machine to boot. This may take a few minutes... [default] Machine booted and ready! [default] Configuring and enabling network interfaces... [default] Mounting shared folders... [default] -- /vagrant
And your vagrant box is running. You can now perform a vagrant ssh and log in to your box, its exactly like a real ubuntu machine where you can install software and configure a web server. But, of course, this is not our main goal: it would be useless if we had to log in and install the environment ourselves, each time we got a new vagrant instance. We'll learn how to do this by using Puppet as a provisioner, in the second part of this tutorial.