Build Virtual Machines Easily With PuPHPet

Share this article

Does creating and managing development environments frustrate you, slow you down, or distract you from development? Do you have issues because your development and deployed environments differ? If so, I’ve got the solution for you – PuPHPet!

Introduction

I can’t speak for you, but one of my pet peeves about software development is environments. Whether it’s creating and maintaining them for different projects with different needs; ensuring environment parity across a development team, (especially when they’re remote); or between environments such as development, testing, and production. Across all of these, it can be a laborious task, especially when done manually.

As we all know, the amount of options, the variety of choice, the demands of the IT manager, team lead, or client can be stressful. They can (and do) pull us in a multitude of directions, oftentimes simultaneously.

There’s database choices such as MySQL, PostgreSQL, Oracle and SQLServer. There’s NoSQL choices such as Cassandra, Hadoop, and Redis. There’s webserver choices such as Apache and Nginx. The list goes on and on.

And when we don’t have a dedicated sys admin team (say we’re a solo freelancer or in a very small team), time taken to maintain development environments becomes really precious – we become DEVOPS.

In pursuit of ending this pain and making the entire process as efficient as possible, I set about the task of learning Vagrant & Puppet. From discussions with colleagues and internet research, these two tools seem to be the standard for creating reusable environments. If you’re not familiar with these excellent tools, here are two short excerpts from their respective manuals:

Vagrant:

Create and configure lightweight, reproducible, and portable development environments. Vagrant will change how you work

Puppet:

Puppet is IT automation software that helps system administrators manage infrastructure throughout its lifecycle, from provisioning and configuration to orchestration and reporting. Using Puppet, you can easily automate repetitive tasks, quickly deploy critical applications, and proactively manage change, scaling from 10s of servers to 1000s, on-premise or in the cloud.

However, like most people in the modern world, I’m impatient. Like you, I have a lot going on, plus I was not seeking to become a guru. I felt there must be a way to come up to speed quickly but without becoming an aficionado.

Enter PuPHPet

After some further googling, I came across the subject of this article, PuPHPet, an excellent GUI tool providing a simple wizard, which creates a Puppet-powered Vagrant configuration, usable immediately.

Originally started a few short months ago by Juan Treminio, PuPHPet makes creating environments perfectly tailored for PHP developers on stacks such as {W,M,L}AMP dead simple.

It focuses on 5 areas:

  • Deploy Target (memory, ip address, port forwarding)
  • Server Basics
  • PHP (modules, libraries, config settings)
  • Database (PostgreSQL, MySQL)
  • Webserver (Apache 2, Nginx)

Whether you want to have PHP 5.5 running PostgreSQL and Nginx or PHP 5.4 running Apache 2 and MySQL, you can rapidly create and download the configuration, getting going in minutes.

Admittedly, there’s a lot more to an environment than these choices; but, to be fair, it’s early days and what it already provides, it does really well.

With PuPHPet, you’ll be up and running inside a half hour, and all you have to do is run:

vagrant up

That’s right. In the uncompressed PuPHPet archive, you need only run that command, wait a bit, and you’re ready to go. Don’t believe me? Let’s step through the process from start to finish together.

After we’re done, I wholeheartedly encourage you to play to your hearts content, changing options, adding removing packages and more and see what you find. I’m confident you’ll be impressed.

Required Software

A word of warning before we start. One of the biggest problems I faced when I first started was having the right versions of both Vagrant and VirtualBox. It appeared as though I’d only get part way and have to do the rest manually. It was never clear what had gone wrong or how complete the process was.

So if you’re finding things aren’t working, try different versions of both packages. I’m currently running Vagrant 1.3.5 and VirtualBox 4.3.2 and they’ve worked flawlessly every time.

Firstly, install a copy of these two packages.

Creating the Configuration

With them installed, open up https://puphpet.com. You can see, right at the top, that there are four initial choices: Local, Digital Ocean, Rackspace and Amazon Web Services. Choose Local as we’re not using these online services in this tutorial.

Under “Local VM Details”, we can specify the VM’s:
– Operating System
– Hostname
– IP Address
– Memory Allocation

For today’s example, we’re using Debian Wheezy 7.2 x64 with VirtualBox 4.3. This allows us to use PHP 5.5 or 5.4. Feel free to leave the remaining three settings as they are, or adjust as suits you best.

Next comes Local VM Forwarded Ports. I’ve not configured it, but if you want to setup some ports on your host machine to forward to ports on the guest VM, then configure them here, as necessary.

Sharing Folders with Local VM

Here we begin to see the power and flexibility that Vagrant and Puppet provide. In Box Sync Folder Source you specify a local directory which will map to a directory on the guest VM at the location specified by Box Sync Folder Target. I’ve left the defaults for both of these and also for Shared Folder Type.

This option is handy if you want to set up a number of custom directories on your VM. Say you have an existing working copy under ~/Documents/workspace/your-project. You could map this to a directory directly in the web root of your VM’s web server. That way you can develop locally, with no syncing or copying requirements to the virtual machine.

Server Basics

If there are specific packages that you need available, such as git, subversion, vim, etc, then list them here. One thing to remember, is you need to know the package name as specified in your chosen operating system. No list is provided in the popup when you type.

Webserver

Apache(2) or Nginx? For this tutorial, I’m going with Apache. The configuration choices are simple and straight-forward. First specify the modules to be installed and enabled by typing in the Apache Modules field. This will popup a list of available options for you to choose from – helping ensure an error free process.

Next comes the Virtual Host configuration. What is the server name and alias of your application? First specify them, then the root directory and port. What we’ll do is set the same directory for the Document Root as we specified in Box Sync Folder Target, to keep things nice and simple. Unless you have a specific need, leave the port at the default 80.

The final two settings, Environment Variables and AllowOverride, only change if your application needs it. For today, the defaults are fine.

PHP

Only a few options are available here, but they’re good enough for what we need. I’ve left the default of PHP 5.5 (why would you want anything else?). I’ve also left Composer selected. If you’ve not used Composer, or are not sure what all the fuss is about, read this excellent post by Ben Ramsey, or this post on Composer here on SitePoint.

Under INI Settings, I’ve accepted the defaults and then added in allow_url_fopen, allow_url_include, error_log, file_uploads, and apc.enabled. Feel free to do the same, or browse and choose from the extensive list.

I’ve changed my PHP Timezone to Europe/Berlin as that’s the closest to me. But change yours as best suits your location. For PHP Modules, my list is cli, intl, mcrypt, cgi, curl, memcached, memcache, pspell, tidy and sqlite. Scroll through the list and add the ones that you need (or would like). For PEAR and Pecl modules, I’ve left these as they were.

I’ve elected to install Xdebug, taking the default settings, but not Xhprof. XDebug is just excellent, so I highly recommend you use it.

Database

Ok, we’re getting serious now. For today’s example, I’ve chosen MySQL, setting the root password to password and left privileges at all. The DB name is sitepoint, the username is testuser and the password, testpassword. I’ve kept the choices here simple, so as not to overcomplicate the situation. I don’t have a SQL script to run on VM load, so have left this blank.

Create & Download the Config

Now, just click the extremely large button Go ahead then, make it. You’ll see the download appear in your downloads directory. After it’s finished, extract the archive and cd into the directory in your terminal. From there, run vagrant up.

This begins the process of building the VM. If you’ve not downloaded a Box file yet or don’t have one matching the operating system you’ve specified, you’ll have to wait a bit longer as it’s downloaded, before the VM can be built. All being well, you’ll see output like the following:

✗ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'debian-wheezy72-x64-vbox43'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Running 'pre-boot' VM customizations...
[default] Booting VM...
[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
[default] -- /var/www
[default] -- /tmp/vagrant-puppet/manifests
[default] Running provisioner: shell...
[default] Running: /var/folders/_w/k6fxbl615w700lgkrtt0vb3w0000gn/T/vagrant-shell20131126-3538-kid3ga
stdin: is not a tty

 ____        ____  _   _ ____      _      generated using
|  _ \ _   _|  _ \| | | |  _ \ ___| |_   ___ ___  _ __ ___
| |_) | | | | |_) | |_| | |_) / _ \ __| / __/ _ \| '_ ` _ \
|  __/| |_| |  __/|  _  |  __/  __/ |_ | (_| (_) | | | | | |
|_|    \__,_|_|   |_| |_|_|   \___|\__(_)___\___/|_| |_| |_|

Created directory /.puphpet-stuff
Running initial-setup apt-get update
Finished running initial-setup apt-get update
[default] Running provisioner: shell...
[default] Running: /var/folders/_w/k6fxbl615w700lgkrtt0vb3w0000gn/T/vagrant-shell20131126-3538-1116fzj
stdin: is not a tty
Downloading http://apt.puppetlabs.com/puppetlabs-release-wheezy.deb
Finished downloading http://apt.puppetlabs.com/puppetlabs-release-wheezy.deb
Running update-puppet apt-get update
Finished running update-puppet apt-get update
Updating Puppet to latest version
dpkg-preconfigure: unable to re-open stdin: No such file or directory
Finished updating puppet to latest version: Puppet v3.3.2
Created empty file /.puphpet-stuff/update-puppet
...
Info: Creating state file /var/lib/puppet/state/state.yaml
Notice: Finished catalog run in 436.21 seconds

This indicates that everything has gone well.

Check Everything’s Working

Now that the Virtual Machine’s built, login and check it out. To do that, from the same directory, run vagrant ssh. Once you’re in, to quickly validate all’s ok, run sudo netstat -tlnp. This shows what services are running. It should give you output matching the following

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1643/rpcbind    
tcp        0      0 0.0.0.0:39284           0.0.0.0:*               LISTEN      1678/rpc.statd  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      2643/sshd       
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      13637/postgres  
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      2399/exim4      
tcp6       0      0 :::111                  :::*                    LISTEN      1643/rpcbind    
tcp6       0      0 :::80                   :::*                    LISTEN      31623/apache2   
tcp6       0      0 :::22                   :::*                    LISTEN      2643/sshd       
tcp6       0      0 ::1:5432                :::*                    LISTEN      13637/postgres  
tcp6       0      0 ::1:25                  :::*                    LISTEN      2399/exim4      
tcp6       0      0 :::37887                :::*                    LISTEN      1678/rpc.statd

There you see that Apache and PostgreSQL are running. If you look under /etc/apache2/sites-enabled/ you’ll see a configuration for your virtual host, using a pseudo-random name. If you’ve added the hostname to /etc/hosts on your local machine, then you can open up the hostname in your browser and view the page that results.

We’re Done!

So there you have it. Ok, the first time through, like anything, it might seem like a lot of steps to perform. But as you become more familiar, you’ll get a lot faster. What’s more, you don’t need to recreate from scratch every time.

If you drag puppet/hieradata/common.yaml onto puphpet.com, it will automatically fill out the form to match the configuration contained. Then just adjust to match you needs. So once you’ve done the first one, subsequent ones are much quicker and easier.

Thoughts?

What do you think? Are you keen to use it, and leave the days of building Virtual Machines by hand behind? Share your thoughts in the comments.

Matthew SetterMatthew Setter
View Author

Matthew Setter is a software developer, specialising in reliable, tested, and secure PHP code. He’s also the author of Mezzio Essentials (https://mezzioessentials.com) a comprehensive introduction to developing applications with PHP's Mezzio Framework.

PHPpuphpetpuppetvagrantvirtual machineVirtualizationVM
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week