Vagrant makes the development box the same box for everyone

Three developers on three laptops running three PHP builds against three MySQL versions produce bugs that only reproduce for one of them, and a production server that resembles none of the three. Vagrant puts a VirtualBox machine behind a file in the repository, so the environment is checked out with the code.

# Vagrantfile
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.56.20"
  config.vm.synced_folder ".", "/var/www/app", :nfs => true

  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
  end

  config.vm.provision :shell, path: "provision/bootstrap.sh"
end

The virtual machine is not really the point — provision/bootstrap.sh is. Once the server build is a script under version control, “works on my machine” becomes a diff, and the same script is what gets run on the real host. Two things cost time. The shared folder is slow: VirtualBox’s own sharing over a tree of several thousand files is slow enough that people give up on the idea entirely, and NFS fixes it at the price of a host-only network and a sudo prompt on every vagrant up. And the provisioning script has to be idempotent, because it re-runs — one that appends a line to /etc/hosts will append it again. Make vagrant destroy followed by vagrant up a routine rather than an event, or the box drifts and stops being the shared one.