Skip to content
An Ubuntu 14.04 VM for PHP with built in profiling
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
PACKAGES.txt Fix /opt typo Feb 24, 2018


Instructions if you've used Vagrant before. If you are new to Vagrant, read on.

Table of Contents generated with DocToc

There are a ton of Vagrant base boxes available for web developers. Or, Chef / Puppet configurations to take a basic OS install and configure it "just right". There's two key problems I've run into with other projects:

  • Reverse-engineering the configuration to make minor changes took more time to make than it would have been to build a box from scratch.
  • Many boxes look useful, but aren't signed by a trusted source. How would I know that the box wasn't sending off my API keys or code to some random server?

With the release of Ubuntu 14.04, I needed to get up to speed on Apache and PHP configuration anyways. As well, I wanted something that would easily let me do PHP profiling. So, here's the results of that effort (even though 99% of it is likely completed elsewhere).


  • < 5 minute setup time for new users.
  • Everything you need for most PHP applications.
  • XDebug built in for PHP debugging.
  • xhgui built in and configured for easy opt-in profiling.
  • Linux MySQL Manager for snapshotting databases.
  • Drush included for Drupal dev (and out of the way for everything else).
  • No provisioning whatsoever; treat boxes as "fork and forget" for new projects.

Choosing between xAMP, Vagrant, and Docker

Deciding what local development environment to choose for you and your team can be tricky. Here are three options, ordered in terms of complexity:

  1. Is your team entirely new to PHP and web development in general? Consider using something like MAMP instead of Vagrant or Docker.
  2. Does your team have a good handle on web development, but are running into the limitations of running the site on macOS or Windows? Does your team have mixed operating systems including Windows and Linux? Are your production database imports locally slowing your team down? This Vagrant box aims to address all of these use cases.
  3. Is your team using Docker in production, or already maintaining Dockerfiles? If so, consider using docker4drupal or similar.

Box Requirements

If this is your first time you are using Vagrant, you will need:

  • Git, to be able to clone this repository. Mac users should update git using Homebrew, but it's not required. Windows users can use the excellent Babun or get Git directly from
  • VirtualBox, used to run virtual machines. Make sure you are using the latest version from the website.
  • Vagrant, the CLI tool to manage virtual machines easily. Make sure you are using the latest version from the website.

This Vagrant box will always support the latest versions of VirtualBox and Vagrant, which are both updated regularly. If you encounter any problems while following the instructions below, please double-check that you are using the latest versions of VirtualBox and Vagrant.

Box Setup

  1. Clone to get the base Vagrantfile. Name your clone after your project, such as ~/drupal8. Create new clones of this repository for each different project you work on.

    $ git clone drupal8

  2. Open up the Vagrantfile in your text editor of choice.

    • Each modification in the Vagrantfile is marked with an all-caps header such as PRIVATE NETWORK. Use this to easily jump around in the file with search.
  3. Decide on a hostname for your VM.

    • Set a HOSTNAME for your VM, such as drupal8.local.
      • Your hostname must end in .local for automatic DNS to work. If you decide to use a different hostname, you will likely need to add a line to your /etc/hosts with the bridge IP of the VM. This can be found by running ifconfig eth1 on the VM, though you might consider configuring a STATIC_IP for this in your Vagrantfile instead, as that IP may change.
      • If your system does not support ZeroConf / Bonjour (most do)
        • Windows users can install Bonjour for Windows
        • Linux users can install avahi if it's not installed.
        • Or, manually add a line to /etc/hosts or C:\Windows\System32\drivers\etc\hosts with your desired hostname and IP address.

    • By default Virtualbox syncing and a www directory are synced.
    • The only assumption is that whatever is mounted into /var/www has a docroot directory. If your project uses another directory, you can add a symlink by running ln -s <repository docroot> docroot, or by editing the Apache configuration in /etc/apache2/sites-enabled.
    • Most users will want to use NFS or rsync.
    • For larger codebases, a significant performance improvement can be seen by switching to rsync instead of NFS. Windows users might want to try smb mounting.
  5. Boot the VM with vagrant up [--provider vmware_fusion]. The base box will be automatically downloaded.

  6. Browse to the hostname you choose to see phpinfo or the code you have synced.

Optional setup

Configure RESOURCES to change the defaults of a single CPU core and 512MB of memory. Change ARCH under RESOURCES to 64 to run a 64-bit box instead. This will increase the base memory requirements for the box to boot from around 180MB to 250MB.

You can also verify your download. GPG and SHA1 signatures are available in the Dropbox folder. Vagrant will automatically verify the sha1 signature in the base box JSON file. Unfortunately vagrant won't preserve the raw box after importing it, but for most uses simply verifying the PGP signature on the sha1 hashes and JSON files should be enough.

Drupal Installation

These instructions will be fairly similar for any other PHP app checked out from git. Most systems will require a composer install, which can be run from inside the VM or on the host machine.

  1. Remove the default docroot directory, since we are going to replace it with a Drupal checkout:

    $ cd www
    $ rm -rfv docroot
  2. Go to to clone Drupal 8 to get directions to checkout Drupal. It needs to be cloned into the www/docroot directory within your project directory.

    $ git clone docroot

Browse to http://drupal8.local and install Drupal. Use root with a blank password as the MySQL database credentials. The installer will automatically create a database for you.

Basebox Details

/etc management

/etc is managed with etckeeper which is configured to commit to a git repository. Run sudo git log -p in /etc to see all of the configuration changes made since the initial installation.

The git repository for /etc is available at trusty32-lamp-etc.


The default group for the vagrant user has been changed to www-data. As well, /var/www is owned by vagrant:www-data.


Grub has been configured with a three second delay so it's actually possible to get to the menu when booting a VM.

"Unable to mount shared folders" fixed

The VirtualBox additions install to /opt, but /sbin/mount.vboxfs expects them in /usr/lib. A symlink has been added from /usr/lib/VBoxGuestAdditions to fix this.

Apache configuration

Apache is configured to serve /var/www/docroot as the primary site. That directory is set to AllowOverride All.

Package highlights

  • LAMP stack composed of
    • Apache 2.4
    • MariaDB 5.5
    • PHP 5.6 and PHP 7.0 (using mod_php)
    • memcached 1.4
    • redis 2.8
  • zsh and oh-my-zsh
  • vim-full instead of vim-tiny
  • Drush, installed from git into /opt
  • xhgui and xdebug

See PACKAGES.txt for the full list.

MariaDB (MySQL) Configuration

Maria is configured to only listen on localhost, with a passwordless root account. To connect to the database:

$ vagrant ssh # If you aren't already ssh'ed in.
$ mysql -u root -p

To connect from an outside tool like Sequel Pro, use your tool's SSH tunnel configuration. For SSH, use the hostname you set in the Vagrantfile and vagrant as the username and password. You can also use the SSH key placed in your project's .vagrant folder.

Sequel Pro Configuration

Changing PHP Versions

Apache and command line PHP by default are configured to use PHP 5.6.x. If you would like to use, for example, PHP 7.0.x, run the following commands:

$ vagrant ssh # If you aren't already ssh'ed in.

# Switch to using PHP 7.0 on the command line
$ sudo update-alternatives --set php /usr/bin/php7.0
# Check to make sure your PHP version is correct now.
$ php -v

# Update Apache to use PHP 7.0 instead of PHP 5.6
$ sudo a2dismod php5.6 && sudo a2enmod php7.0
# Now restart Apache
$ sudo apachectl restart

Note: If you've altered anything in php.ini for PHP 5.6, you will need to make those same changes in /etc/php/7.0.

PHP Debugging with xdebug

xdebug is installed and preconfigured to allow remote connections for debugging. See your editor or IDE for instructions on how to start a debugging session. For PHPStorm, the bookmarklet generator works well.

For CLI and Drush debugging, use the included php-debug script to start a shell with debugging enabled. First grab the host name or IP of your local machine (for example run hostname -f). Next SSH into your Vagrant box and run:

$ php-debug <hostname of local machine>

Next ensure that your debugging client on your local machine is listening for connections (eg. in PHPStorm: Run > Start Listening for PHP Debug Connections). Finally run your CLI and Drush commands from the Vagrant box and xdebug should connect to PHPStorm and allow you to start stepping through.

PHP Profiling with XHGui

XHGui is installed to /opt and preconfigured to profile PHP requests. Profiles are kept for 5 days, and indexes have been added as recommended by the xhgui setup instructions.

To start profiling simply append ?xhgui=on to a request. This will set a cookie that will keep profiling enabled for the next hour, regardless of the query parameters. Browse to /xhgui to view your profiles.

It is likely that your project doesn't include the XHGui code that is included to start profiling. When debugging, your IDE might show steps through this code as unmapped code.

Options include:

  • Set a breakpoint within your project, and run to it.
  • Or, download XHGui to your machine and add it to the include path in your project. Map the XHGui source directory to /opt/xhgui on the "remote" machine. The exact configuration for this is IDE dependent.

Fast database dumps and restores with MySQL Parallel

MySQL Parallel is included to facilitate faster imports and exports of databases. Run mysqldumpp and mysqlrestorep for details, or see /opt/mysql-parallel.

Email Configuration

Setting up an email system that works in all cases is difficult to do. Some may need no email at all, while others want email to be forwarded to some other system. If email is required, try either:

Drush Alias Autoconfiguration

For Drupal developers, this repository includes a Drush alias that automatically creates an alias of @HOSTNAME.local. A small snippet must be included in ~/.drushrc (or ~/.drush/drushrc.php) in the host machine for this file to be loaded by Drush:

$dir = getcwd();
while ($dir != '/') {
  if (in_array('site-aliases', scandir($dir))) {
    $options['alias-path'][] = $dir . '/site-aliases';
  $dir = dirname($dir);

For advanced networking configurations, simply add a custom alias at the bottom of aliases.drushrc.php.

Verifying basebox integrity

Verifying the download when adding the box

vagrant box add --name=trusty32-lamp --checksum [] --checksum-type=sha1 [url-to-box]

Verifying the box manually

  1. Download the box directly.
  2. Download the corresponding .sha1 file.
  3. shasum -c

Validating my identity

  1. Download the box directly.
  2. Download the corresponding .asc file.
  3. gpg --recv-keys CEBFC72B # Or download CEBFC72B.asc from dropbox and import it.
  4. gpg --verify
    • GPG will throw a warning about the signature not being trusted unless you or someone else in your web of trust has signed my key.

Updating baseboxes

  1. vagrant destroy any existing box in your working directory.
  2. Set USE_INSECURE_KEY to true in the Vagrantfile.
  3. Set PROVISIONING to true in the Vagrantfile.
  4. Run vagrant up.
  5. Run vagrant provision until it passes.
  6. Run vagrant reload to verify any upgraded kernels.
  7. Update the Virtualbox guest additions.
  8. Push any changes in /etc/ to
    • Any explicit changes should be manually committed and shared with other repository branches.
  9. Use apt-get purge to remove any old linux-image and linux-header packages to save disk space.
  10. Run vagrant reload just to make sure grub is still working.
  11. Run vagrant snapshot push && vagrant ssh --command='sudo /vagrant/' && vagrant snapshot pop to ensure that the web server, xdebug, and xhgui are working.
  12. Run vagrant ssh -c /vagrant/zero-free-space to zero free space on the disk.
  13. Halt the box.
  14. Compact the VMDK file with:
    • Using VMWare:
      • /Applications/VMware\ -d box-disk1.vmdk
        /Applications/VMware\ -k box-disk1.vmdk
    • Using compact-vmdk:
      • Make sure qemu-img is available.
      • compact-vmdk box-disk1.vmdk
  15. Package the box for:
    • Virtualbox: vagrant package --output
    • VMWare: cd <path-to-the-vm> && tar cvf - ./* | pigz -v > ../
  16. shasum >
  17. Sign the sha1sum with GPG. gpg -sabu <your-email>
  18. Sign the base box with GPG. gpg -sabu <your-email>

Converting a VirtualBox box to VMWare

I'm not building VMWare images anymore. If anyone is interested in building and maintaining them, please open an issue.

While it's easiest to update the existing VMWare base box, sometimes it's better to update a VirtualBox box and then convert it work with VMWare.

  1. vagrant up the base box in VirtualBox.
  2. Export the virtual machine to an OVF file using the GUI.
  3. Import the VM into VMWare, ignoring any warnings.
  4. Add a CD drive to the VM.
  5. Install VMWare tools.
  6. Reboot the VM to verify that the VMWare tools are working correctly.
  7. Use zero-free-space inside the VM to aid in disk compacting.
  8. Halt the VM.
  9. Use vmware-vdiskmanager as above to defrag and compact each VMDK.
  10. Create metadata.json inside of the VM package directory.
  11. Remove any log or other unneeded files from the package directory.
  12. Package the box using the above tar command.
You can’t perform that action at this time.