Creating a virtual server with Vagrant: a practical walkthrough

DZone 's Guide to

Creating a virtual server with Vagrant: a practical walkthrough

· DevOps Zone ·
Free Resource

Vagrant ia a tool for building virtual machines (in VirtualBox's format) that conforms to a specification. It's written in Ruby, but it makes really no assumptions over the environments that you're gonna build; in this article, we will setup a virtual server for PHP applications running inside Apache.

The goals

Vagrant is a faster way to build reproducible machines: you can store metadata about the packages that you want to install in a Linux box, and then recreate a new instance of the virtual machine any time you want.

It's a lightweight alternative to storing one image file for each configuration; moreover, image files are to a Vagrantfile what binaries are to source code. It's much easier to modify a concise list of packages that booting a virtual machine and starting to delete files and run lots of apt-get commands.

The machines you build will be available for anyone in your team, so they will be able to reproduce a bug as if they were in production. The consistency goes along several dimensions: the OS, installed software and libraries versions, and the configuration files in /etc and elsewhere.

The machines produced by Vagrant are based on Virtualbox, an open source solution first pursued by Sun and now by Oracle after its acquisition.


Vagrant is written in Ruby, and distributed as a gem (a mechanism similar to PEAR for PHP packages). In Ubuntu, install the package rubygems to get access to the gem command.  On Ubuntu Oneiric, gem has some problems: fix its configuration to ensure Vagrant can be installed with:

[giorgio@Desmond:~]$ sudo gem install vagrant

Now for the first VM

Following the getting started guide, we can get a Ubuntu Lucid box to avoid starting from scratch:

[giorgio@Desmond:~]$ vagrant box add lucid32 http://dl.dropbox.com/u/7490647/talifun-ubuntu-11.04-server-i386.box

This command will download a 372 MB box file, but it's better than downloading a .iso and having to install it on a new virtual machine. Boxes are global, so they will be stored in ~/.vagrant.d/boxes and you will be able to reuse them in the creation of many different machines. They are just a starting point, containing not only the files but also the configuration of RAM, disk space and so on.

Create a folder for our configuration:

[giorgio@Desmond:~]$ mkdir john && cd john

Every vagrant command should be run inside this folder now, so that it targets the current machine's environment.

Create the Vagrantfile, which is the equivalent of a makefile for virtual machines:

[giorgio@Desmond:~]$ vagrant init lucid32

Now you will notice a Vagrantfile text file inside the folder:

Vagrant::Config.run do |config|
  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "lucid32"
  # (everything else is commented)
  # ...

vagrant up will start the machine, which doesn't do anything for now. vagrant destroy will delete the machine, but it will be recreated from the configuration at your will.

The software

However, first we need to setup some packages. We will use a simple Puppet manifest to specify the packages for Apache and PHP, but nothing fancy (I'm not even an expert in Puppet yet.)

[giorgio@Desmond:~/john]$ mkdir manifests
[giorgio@Desmond:~/john]$ touch manifests/lucid32.pp
We can specify which packages to install in lucid32.pp:
class lucid32 {
  exec { "apt_update":
    command => "apt-get update",
    path    => "/usr/bin"

  package { "php5":
    ensure => present,

  package { "libapache2-mod-php5":
    ensure => present,

  package { "apache2":
    ensure => present,

  service { "apache2":
    ensure => running,
    require => Package["apache2"],

include lucid32

Let's modify the Vagrantfile to include it:

Vagrant::Config.run do |config|
  # Enable the Puppet provisioner, which will look in manifests/
  config.vm.provision :puppet

  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "lucid32"

Port forwarding

Before creating the machine, let's setup also portforwarding so that we can access the virtual machine on a specific port of localhost:

  # Forward guest port 80 to host port 4567 and name the mapping "web"
  config.vm.forward_port("web", 80, 4567)

vagrant up will create the machine now. If something goes wrong, execute vagrant destroy, modify your configuration, and try again with vagrant up.

Executing PHP files

How do we know the machine is working? Let's create a phpinfo.php file in the machine's folder:


We have SSH access as the user 'vagrant', by simply executing vagrant ssh. There is also a shared folder between the host and the guest machines, which is the folder in which we are now.

On the VM's, this folder is mounted in /vagrant. So we can copy the PHP file via SSH to test our machine:

[giorgio@Desmond:~/john]$ vagrant ssh
vagrant@lucid32:~$ sudo cp /vagrant/phpinfo.php /var/www/

We also need to restart Apache, since after the installation I haven't found a comfortable way to automatically restart it in order to make it interpret PHP files:

vagrant@lucid32:~$ sudo /etc/init.d/apache2 restart

Feel free to add suggestions on how to automate this step with Puppet, as you probably know it better than me.

Now load http://localhost:4567/phpinfo.php:

Terminating execution

vagrant halt will shutdown the machine, while vagrant destroy will also throw away everything (the image file, but not the configuration). Suspension and resume can be performed via vagrant suspend and vagrant resume, but the content of the RAM will take space on your disk since it needs to be stored.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}