Development Environments the Right Way with Vagrant and Puppet
As long as I can remember, I have used some form of MAMP/WAMP stack for development. I'd download the entire stack pre-packaged with some sort of control console, and develop web applications straight out of my Dropbox folder (with Git as version control), changing the web root of the *AMP configuration depending on which project I am working on.
What's Wrong with XAMPP/MAMP?
The primary reason XAMPP and MAMP are wrong tools to use for development is due to the software stack's differences from your production environment. While they likely aren't far off, it's these subtle differences that will catch you off guard and make your web application fail in testing or staging environments. Worse yet, if you don't have a proper testing or staging environment configured, you may only run into these bugs once you've deployed your website or application into production.
Even developers that run a LAMP stack on a Linux development machine will encounter problems due to the idiosyncrasies of different Linux distributions, compiled server binaries, and installed dependencies. More often than not you'll forget you had to manually install an extra package at some point in the past, and will be caught off guard when your app throws and exception with a missing dependency error in production.
How Does Vagrant Help?
Vagrant is a solution to this problem. Essentially, Vagrant is a wrapper around the VirtualBox virtualization platform that manages headless server instances for you.
With a single command,
vagrant up, I have Vagrant setup to launch an Ubuntu 12.10 x64 Server instance and install a common LAMP stack through Puppet, with various dependencies and extra packages such as Git. All of this is done in about five minutes, without my intervention. Once the setup is complete, I point my web browser to
localhost:8080 and can immediately see my web application running.
The automation is nice to prevent tedious recreation of the environment for every new development machine, but it also means that I get the same environment no matter what operating system I choose for development. On my Windows desktop workstation and my Macbook Air, Vagrant creates the exact same virtual machine, complete with the same amount of RAM, and LAMP stack running on the same version of Ubuntu.
As a bonus, there are several plugins that allow you to spin up servers at remote providers, such as AWS or Digital Ocean. This even removes the discrepancies between VirtualBox's emulation and the virtualization platform your production hosting provider uses.
What is Puppet?
While Vagrant manages the virtual machine and allows me to spin up and destroy the instance at will, Puppet is the tool that performs the magic of installing Apache, MySQL, PHP, and other packages such as Git. Normally, I'd have a long checklist of packages that I needed to ensure were installed in the virtual machine, but Puppet manages these automatically.
Essentially, I have a configuration file that says "ensure the following packages are created and directories are writable, and if they aren't, make them that way". Puppet follows these instructions and only performs the necessary actions. You can run the Puppet manifest on an already booted machine or a completely new instance, and end up with all of the required packages either way.
Why Take the Time to Set These Tools Up?
Before Vagrant and Puppet, I managed a production server and my development environment separately. It worked 99% of the time, but the 1% it doesn't becomes a large hassle. When I started running into issues with differences between environments, such as missing
php5-mcrypt or having incorrect permissions on a specific folder, it can take precious time to find and fix these bugs.
In particular, while upgrading a PHP package for my welcome bar service ThreeBar, I ran into a peculiar issue that boiled down to missing dependencies, which I had installed on my Macbook Air through MAMP but not the Ubuntu server that is used in production. After several hours debugging the application on my test server, I was able to find a solution-- but at the cost of wasted time.
I'm sure, you, as a developer, have also encountered these same issues, of which Vagrant and Puppet are solutions to. Though they both take some configuration to setup initially, once done, you won't have to think about setting up another server by hand again.
To give you an insight to my development process for ThreeBar, here's an example of how I take a newly formatted development workstation to a fully setup development machine:
- Install GitHub for Windows, or the command line Git for Mac/Linux (this depends on the workstation's OS)
- Install VirtualBox and Vagrant
- Clone the Git repository for ThreeBar
vagrant up webto launch a new virtual machine. This downloads a Ubuntu 12.10 x64 Server image, launches it, and installs the Puppet manifest
- Wait until setup is complete
vagrant ssh webto launch a SSH session into the VM
cd /var/www; php composer.phar install; php artisan optimizeto install the Composer dependencies and run Laravel's bootstrap file generation tool.
To ensure none of these steps are missed, the Git repository has a Readme file with all of the above steps.
After these steps are done, I can point my web browser to
localhost:8080 to see a development version of ThreeBar running. The last couple of steps can be automated, but I haven't done so yet because they only need to be run once when the Git repository is initially cloned.
How to Get Started
If you are looking to get started with Vagrant or Puppet, take a look at some of the following resources. The examples, in particular, and great to understand how to use the two applications.
I heavily based my initial configuration off of some of these examples, though they have been modified to install additional dependencies needed by my application.