In part one of this series, we considered the problem of how to create and manage development environments in a way which was simple, repeatable, and (even) efficient. It’s a problem which I’m confident we’ve all run in to from time to time. The solution was a relatively new tool called PuPHPet.

If you missed part one, PuPHPet creates a Vagrant + Puppet configuration based on five key areas:

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

We looked at how to configure most of the options and how to use the generated configuration, with some basic vagrant commands. But that’s as far as we went.

So in this second part of the series, we’re going further. Specifically, we’re going to be looking at the two core files used: common.yaml, and Vagrantfile. We’ll be making some changes to them, then provisioning the virtual machines to reflect the configuration changes.

This series won’t make you a master of either Puppet or Vagrant, but by the end of it, you’ll have sufficient knowledge to make changes to the configuration generated by PuPHPet, so you can adapt your virtual machine, as your needs change.

NOTE: please be aware that there have been some important changes in Puppet and Vagrant, which affect PuPHPet. Please pay particular attention to the two notices at the top of the PuPHPet site – especially if you’ve been experiencing any difficulties following part one of this series. If the notices are gone, the problems are, too.

Provisioning Changes

For our purposes today, there is one key command which you need to know, vagrant provision. Quoting the manual:

This command is a great way to quickly test any provisioners, and is especially useful for incremental development of shell scripts, Chef cookbooks, or Puppet modules. You can just make simple modifications to the provisioning scripts on your machine, run a vagrant provision, and check for the desired results. Rinse and repeat.

We’ll be using it to roll out our environment changes.

Altering Shared Folder Configuration

One of the things that you’ll likely want to do first is to adjust the configuration of the shared folders. Assuming the original configuration from the first part in the series, here’s what the relevant section of Vagrantfile looks like.

config.vm.synced_folder "/Users/matthewsetter/Documents/workspace/my-great-app", "/var/www/my-great-app", id: "vagrant-root", :nfs => false

You see that I’ve set up a shared folder in my workspace directory with the same name under /var/www/ in the virtual machine. Recently I was setting up a new Vagrant VM for a client’s project. I found that my Zend Framework 2 application couldn’t write to the cache directory. Looking at the directory structure of the project, in the virtual machine, all of the directories were owned by the user vagrant; but the webserver user (and group) was www-data. So it wasn’t able to read. I saw two options:

  1. Change the permissions to 777
  2. Change the owner and group

To me the second was the more intelligent choice. But how to do that? As it turns out, it is quite simple. At the end of the configuration above, we need to specify the owner and group as www-data. I’ve done this in the updated configuration below.

    config.vm.synced_folder "/Users/matthewsetter/Documents/workspace/my-great-app", "/var/www/my-great-app", id: "vagrant-root", :nfs => false, owner: "www-data", group: "www-data"

To roll out the change, update the file Vagrantfile in your Vagrant configuration, save the file, then from the command line, run the command: vagrant provision. All being well, you’ll see output similar to the first time you called vagrant up, but much shorter, as only a few changes are being made – not the entire VM being provisioned. When it’s done, ssh in to the VM with vagrant ssh, then have a look at the permissions on the project directory. They should look like the output below:

    $ ls -lahrt /var/www/my-great-app/
    total 3.1M
    drwxrwxrwx 1 www-data www-data  102 Oct 15 05:00 data/
    -rw-rw-rw- 1 www-data www-data 856K Oct 15 05:00 composer.phar
    -rw-rw-rw- 1 www-data www-data  607 Oct 15 05:00
    -rw-rw-rw- 1 www-data www-data  259 Oct 15 05:00 .gitmodules
    -rw-rw-rw- 1 www-data www-data  338 Oct 15 05:00 .gitignore
    -rw-rw-rw- 1 www-data www-data 1.8K Oct 15 05:00 init_autoloader.php
    drwxrwxrwx 1 www-data www-data  340 Oct 15 05:00 db/
-rw-rw-rw- 1 www-data www-data 2.2M Oct 15 05:00 zftool.phar

Altering PHP’s Configuration

So far, so good. Let’s look at the PHP configuration and make some changes. Below is the original configuration generated by PuPHPet in part one. You’ll find it in vagrant/puppet/hieradata/common.yaml. It shows the PHP version is 5.5, composer’s enabled, the php modules, ini settings and the default timezone.

    version: '55'
    composer: '1'
            - cli
            - intl
            - cgi
            - curl
            - mcrypt
            - memcache
            - memcached
            - pspell
            - tidy
            - sqlite
        pear: {  }
            - pecl_http
        display_errors: On
        error_reporting: 'E_ALL & ~E_STRICT'
        apc.enabled: '1'
    timezone: Europe/Berlin

Let’s make some changes. Let’s change:

  • the timezone to ’Europe/London’
  • the session save_path
  • some other runtime options:

Specifically, update from ini: down with the following:

        display_errors: On
        error_reporting: 'E_ALL & ~E_STRICT'
        apc.enabled: '1'
        session.save_path: /tmp
        allow_url_fopen: '1'
        allow_url_include: '1'
        error_log: syslog
        file_uploads: '1'
    timezone: Europe/London

You’ll likely recognize the ini directives from the PHP Manual so I won’t rehash them here. But you can see that they’re as easy to configure here as they are in the PHP ini file. Actually, let’s go out on a limb and make a decent change.

After doing so, here’s the new PHP settings:

  • session.save_path => /tmp => /tmp
  • allow_url_fopen => On => On
  • allow_url_include => On => On
  • file_uploads => On => On
  • error_log => syslog => syslog
  • Default timezone => Europe/London
  • date.timezone => Europe/London => Europe/London

Note: If you’d like to pick a different timezone, here’s the list supported by PHP.

Now I’m sure you’ll agree that being able to change a PHP configuration, just by changing a text file, is powerful, very powerful. Imagine the amount of work you’ve likely done in the past to achieve this.

Altering XDebug Configuration

If you’ve been using PHP for any amount of time, you’ve likely been using Derek Rethan’s XDebug package. In part one, we took the basic setup offered in PuPHPet. Let’s make some modest changes to it and again provision the virtual machine to enable them. Below is the original configuration in common.yaml.

    install: '1'
        xdebug.default_enable: '1'
        xdebug.remote_autostart: '0'
        xdebug.remote_connect_back: '1'
        xdebug.remote_enable: '1'
        xdebug.remote_handler: dbgp
        xdebug.remote_port: '9000'

Add in the following options to it, remembering to respect the indentation, otherwise you’ll have problems.

    xdebug.auto_trace = 1
    xdebug.idekey = "SITEPOINTPHP"
    xdebug.profiler_enable = 1
    xdebug.profiler_output_dir = "/tmp/xdebug.profiler"

There’s no specific reason for these configuration options over any other. They’ve been randomly picked just to play with XDebug. So feel free to choose other options if you wish.

As before, call vagrant provision, wait a bit for the provisioning process to complete. Then we can check that the process’ been successful by again looking at the running PHP configuration with:

php -i | grep -i xdebug
  • xdebug.auto_trace => On => On
  • xdebug.idekey => SITEPOINTPHP => SITEPOINTPHP
  • xdebug.max_nesting_level => 100 => 100
  • xdebug.profiler_enable => On => On
  • xdebug.profiler_output_dir => /tmp/xdebug.profiler => /tmp/xdebug.profiler

Altering MySQL’s Configuration

Ok, one last one. Let’s make changes to MySQL and have a bit of fun. We’ll change the user account name and password, install and enable phpmyadmin. We’ll finish by making the user’s privileges a bit more restrictive. Not a bad list of tasks. No?

Think for a moment just how long that’d take if you did it all by hand. No, seriously. maybe you already have provisioning scripts for this; maybe you do it all by hand; but either way it takes time.

Note: I’ll be honest, I’m not a MySQL admin; so there’s tools I won’t be aware of. If you are, please mention some in the comments.

As before, below is the originally generated configuration so you know what it looks like.

    root_password: password
    phpmyadmin: 0
                - ALL
            name: testdb
            host: localhost
            user: testdb_couser
            password: testdb_password
            sql_file: ''

Below is the updated version, showing what it looks like with the changes I mentioned above. You see that the username and password have changed, I’ve set 1 next to phpMyAdmin to enable & install it.

    root_password: password
    phpmyadmin: 1
                - INSERT
                - SELECT
                - 'SHOW DATABASES'
                - UPDATE
                - USAGE
                - INDEX
                - DELETE
                - CREATE
                - ALTER
            name: testdb
            host: localhost
            user: testdb_username
            password: testdb_P@$sw0rd
            sql_file: ''

Let’s provision the virtual machine again and see what’s changed. After running vagrant provision, I’m able to login with the new username and password, and phpMyAdmin is available at


So, what do you think? Do PuPHPet, Vagrant, and Puppet make managing a development environment really simple? So many things which may have been done manually, or with hand written bash scripts don’t need to be any longer.

As you followed along, did your provisioning run as smoothly as mine did? Did you encounter any issues that you need a hand with? If so, feel free to email me directly.

Otherwise, I hope that you’ve been bitten by the bug that is Vagrant, Puppet, and PuPHPet. I also hope you’ve seen just how easy it is to adjust your environments, on the fly, to match your changing needs, through nothing more than 2 version controlled text files and a handful of commands.

Please 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 ( a comprehensive introduction to developing applications with PHP's Mezzio Framework.

PHPprovisionpuphpetpuppetvagrantvirtualvirtual machineVM
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form