When I first began using Vagrant, I had a heck of a time trying to figure out how to structure my project. Sure, there were tutorials on how to set Vagrant up but I wanted something even more higher level and in-depth. The following is how I now set up my personal projects. This isn’t set in stone; I modify it each time I find something better that works for me.
I use Vagrant for all development work since I don’t have to mess with my own set-up on my laptop. It makes development easier and quicker, since I mimic whatever server I plan on deploying the project to. For those who don’t know, Vagrant is a way to create development environments. It allows you to share those environments with other developers. Let’s get started!
First, you’ll want to put on some music. Something nice, something soothing ’cause the computer gods always have it in for us little peons and this might just make you frustrated. Personally, I’ve been digging Gracie and Rachel. Then, once you’ve got your headphones on and the music up, download VirtualBox and Vagrant. I run a Mac so this article is going to be geared toward Mac users; however, it should be fairly translatable to any operating system. Once you’ve got VirtualBox and Vagrant downloaded, install them on your computer (if you need help with installation, you’ll need to take a look at their respective documenation).
Okay, you’ve got those installed now? Awesome possum. Now we get to the nitty-gritty. Fire up your terminal. We’re going to take care of a few housekeeping things first before we get to Vagrant. In your terminal, type the following:
$ sudo vi /etc/hosts
Inside of that file, add the following line:
Then, save the file and restart the webserver with:
$ sudo apachectl restart
I use the 192.168.33.XXX addy’s just as a personal convention; right now in my
/etc/hosts/ file, I’ve got close to 20 different entries all starting with 192.168.33.
Next bit of housekeeping is we need to add the base virtual box from which we’re going to build our development environment. You can find different boxes at Vagrantbox.es but for the purposes of this article, go ahead and type (or copy/paste) this into your terminal:
$ vagrant box add --name centos64-x86_64-tut https://github.com/2creatives/vagrant-centos/releases/download/v6.4.2/centos64-x86_64-20140116.box
That should be it for housekeeping.
Folder Structure and Files
Next up is the folder structure. It doesn’t matter where you place this folder, which is part of the gloriousness of Vagrant. Now, instead of throwing my websites in the Sites folder and other projects elsewhere, I just keep a Projects directory with code as a subfolder and all of my different projects inside.
Okay, let’s break this down. The
.gitignore files are for Git, your source control. The
Vagrantfile should be part of the repository so other people can get up to speed quickly. The 2 folders in the project directory are
data, which hold the various files to get the environment set up correctly and
src, which is the actually project you’re working on. Inside
index.php is just a
data folder, you’ll notice 4 files. The
bootstrap.sh is a shell script that is executed once Vagrant has started the virtual box. The
httpd.conf files are used by the bootstrap file. We’ll go into more detail further down, m’kay?
The Vagrantfile is a hot mess of confusing crap; at least, that’s what it was to me when I first started using Vagrant. However, I’ve got a minimal Vagrant file that works for me. Let’s open it up and take a look.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "centos64-x86_64-tut"
config.vm.provision :shell, :path => "./data/bootstrap.sh"
config.vm.network :forwarded_port, host: 8080, guest: 80
config.vm.network :forwarded_port, host: 8443, guest: 443
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.synced_folder "./src", "/var/www/html", type: "nfs"
A few things to note with this file. The
config.vim.box line is referencing the name we gave the virtual box when we ran the
vagrant box add command. You can add as many base boxes as you like and then reference them in the Vagrantfile. I usually prefer a CentOS box for most of my development but when I’m working on gitTasks, I instead use an Ubuntu 12.0 LTS base box.
The next line,
config.vm.provision, tells Vagrant to run the shell commands in
bootstrap.sh. The following 2 are forwarded ports and the
private_network line gives a static ip address, which we have already placed in our
/etc/hosts file. Now, when we go to http://vagrant-tut.local, our virtual machine will show up in the browser. The last line allows us to sync a folder on our host computer to that of the guest computer. By default, Vagrant syncs the folder that the
Vagrantfile is in with
/vagrant on the guest computer. If you were to open that location on the guest computer, you’d see the exact same folder structure that’s in
vagrant-tut folder. However, I want to sync the
src folder with the guest’s
type: "nfs" tells Vagrant to use an NFS server to sync the folders. I’ve noticed a lack of performance, especially when dealing with external API calls or with Sass files, and using the NFS option seems to help. Again, you don’t need to use NFS; your mileage may vary.
bootstrap.sh file is pretty straightforward. It’s just instructions on how to update the box and add the packages you want. Since I plan on using PHP on this box, as well as Apache and Nginx, I’m just going to write the commands that I would normally type into the terminal in my virtual box. Open up
# Update yum and install packages
sudo yum -y update
# Want to include Remi's repo
sudo rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# Install necessary packages
sudo yum -y --enablerepo=remi,remi-php55 install wget nginx httpd php php-common php-cli php-mycrypt php-mbstring php-mysql php-pdo mysql-server mysql-client
# Set up configurations
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bk
sudo cp /vagrant/data/nginx.conf /etc/nginx/conf.d/default.conf
sudo mv /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bk
sudo cp /vagrant/data/httpd.conf /etc/httpd/conf/httpd.conf
# Update the timezone, which always throws an error if not set
sudo sed -i 's/;date.timezone =/date.timezone = EST/g' /etc/php.ini
# Start services
# sudo service mysqld start
sudo service httpd start
sudo service nginx start
# Not using MySQL yet but, if I was, here's how I set it up
# if [ ! -f /var/log/databasesetup ];
# /usr/bin/mysqladmin -u root password 'vagrant'
# echo "CREATE DATABASE cms" | mysql -u root -pvagrant
# echo "GRANT ALL ON cms* TO 'root'@'localhost'" | mysql -uroot -pvagrant
# echo "flush privileges" | mysql -uroot -pvagrant
# touch /var/log/databasesetup
# if [ -f /vagrant/data/initialize.sql ];
# mysql -u root -pvagrant cms < /vagrant/data/initialize.sql
# Need to restart afterwards
# sudo service mysqld restart
# sudo service httpd start
# sudo service nginx start
Once Vagrant gets the box running, the next step is to run all of the above commands. You can pretty much put any commands in here. For more information, head on over to Vagrant’s documentation.
Let’s start the VM!
Now that everything’s in place,
cd into the folder where
Vagrantfile is located. In your terminal, run the following:
$ vagrant up
Vagrant will start the VM, run your
bootstrap.sh file, and run through everything. It can take a while the first time you run it since the update and packages are installed for the first time. Barring any issues, you’ll get the terminal prompt back. Now you can head on over to your browser, load up
http://vagrant-tut.local, and you should see the output of the PHP configuration page.
When you’re done developing and you want to shut down the VM, in your terminal:
$ vagrant halt
halt command shutdowns the VM. When you are ready to start developing again, run the
vagrant up command once more. The only difference now is that the VM doesn’t have any services running (i.e. mysqld, httpd, nginx) so you need to log into the VM and issue the following commands:
$ vagrant ssh
$ sudo service httpd start
$ sudo service nginx start
Everything’s up and running again! If you want to completely remove the VM,
$ vagrant destroy will do that for you. Just remember, when running
$ vagrant up again, it’ll load the
Phew! This was a long article. I’ve put all the files into a Github repo: Vagrant Bootstrap; please feel free to clone and take for a spin. If you have any improvements, please don’t hesitate to make a pull request.