php[architect] logo

Want to check out an issue? Sign up to receive a special offer.

Build a VM for Drupal 8 with Vagrant

Posted by on November 25, 2014

At this year’s php[world] hackathon, I spent my time getting a Vagrant machine configured to run Drupal 8. I know there are other options, like Acquia’s own Dev Desktop, or even Zend Server. However, I like using Vagrant to run my LAMP stacks, especially on OS X. I’ve never been able to easily run xAMP on non-Linux machines. Installing MySQL can be a pain, system updates can change the version of PHP you’re running, and some PHP extensions are really difficult to build—even with Homebrew. Vagrant simplifies getting a working development environment running by automating the provision of a virtual machine for you, usually with a tool like Chef, Puppet, or Ansible. I used the hackathon as an opportunity to check out the shell script provisioner. If you know you’re way around the shell, this is a very straight-forward method since it uses the same commands you’d type in yourself at the terminal. There are a number of other benefits to using Vagrant:

  • Match your development environment exactly to your production server, so there’s no more “works on my machine”.
  • No need to install stuff you don’t need on your main operating system just for one client site.
  • Each site you work on gets its own machine, that you can destroy when the project is done.
  • Save your provisioning scripts in Version Control, to track how they change.
  • Share your Vagrantfile and scripts with colleagues, so everyone works in an identical environment.
  • Easily test code in new environments. How will your codebase run in PHP 5.6? Fire up a new machine and test it.

In this post, I’ll walk through setting up a Vagrantfile and shell script to install Apache, MySQL, PHP on a basic Debian machine; automatically download and extract Drupal 8, and create a database for the site. At the end, we’ll just have to walk through the installation steps in a browser.

Configuring the Virtual Machine

The Vagrantfile describes the machine for a project and how to configure and provision it. It controls things like how to setup networking, map files between the host and guest OS, and run the provisioner we chose. Let’s take a look at some key configuration settings. First, we have to specify the box to build on. These are box images, many provided by the community, that have the base OS and some tools. There are boxes for CentOS, Redhat, and more. The line below tells vagrant to use a Debian 7.4 box that has chef installed (even though we won’t be using chef).

config.vm.box = "chef/debian-7.4"

Next, we configure networking so that our box is accessible from the host OS. Here, I’m using the private_network option, so the box and specifying an internal IP address. If you need your virtual machine to be accessible from other devices on your local network, look into using a public_network.

config.vm.network "private_network", ip: "192.168.33.10"

For this config, I’m just using the default shared folders setting. This maps your project directory to /vagrant/ on the guest OS. If you haven’t used Vagrant before, shared folders map one or more directories from your host machine to paths on the virtual machine. In effect, this lets you work and edit files in your favorite IDE on your machine while the guest OS sees and uses the same files. So, for example, you change sites/default/default.settings.php in PHPStorm in your home OS, and Drupal in the VM will process the changes. If you need to map more directories, see the comments in the default Vagrantfile. For example, to map the web directory to /var/www/drupal8, you’d do something like the following:

config.vm.synced_folder "web", "/var/www/drupal8"

Finally, we have to tell vagrant what do once the machine is booted up in order to configure it. This is done with a provisioner, and there are many to choose from. As I mentioned earlier, I’m using a simple shell script for this machine; specified with the config.vm.provision setting.

config.vm.provision "shell", path: "provision/setup.sh"

Setting Up Additional Components

When you start your box for the first time with vagrant up, the provisioner will take care of installing additional components and configuring them. My first pass at this was a bit naive, though it worked. I later came back and augmented it to check if something was already available (you can run vagrant up --provision to re-provision an existing machine). For example, the following part of the script will setup Apache. First, we test if the Apache configuration is present. If it is, we assume it’s already configured and continue. If it’s not present:

  1. It’s installed from the apt repositories,
  2. The Rewrite module is enabled,
  3. We copy some custom environment settings and change directory ownership so that Apache runs as the vagrant user. This is necessary to allow the web server to copy uploaded files into a folder at sites/default/files.
if [ ! -e "/etc/apache2" ]
then
    echo "Installing Apache"
    apt-get install -y apache2
    a2enmod rewrite
    cp /vagrant/provision/apache2-envvars /etc/apache2/envvars
    sudo chown vagrant /var/lock/apache2
    usermod -a -G adm vagrant
fi

Similarly, later in the script we use wget to download and extract the Drupal 8 source into a web directory. $DRUPAL_SRC is a variable configured at the beginning of the script, for when it changes.

# download drupal
if [ ! -e "/vagrant/web/" ]
then
    echo "Downloading Drupal 8"
    mkdir /vagrant/web/
    cd /vagrant/web/
    wget --quiet $DRUPAL_SRC
    tar --strip-components=1 -xzf `basename $DRUPAL_SRC`
    rm `basename $DRUPAL_SRC`
    rm /vagrant/web/sites/default/default.settings.php
fi

Take a look at the complete script to familiarize yourself with what it does.

Provisioning with Ansible

At the same hackathon, Sandy Smith worked on setting up a similar machine with Ansible. We had a friendly competition going over who’s method would work first, and we both hit a few snags. Learn more about provisioning with Ansible in the September 2014 issue In the end, there wasn’t much of a difference. However, the Ansible provisioner reuses existing “roles” coupled with variables you specify. This leads to much smaller “playbooks” to configure a new machine. It also takes care of tracking what changes have been made if you re-provision a box.

---
- hosts: all
  sudo: true
  vars:
    web_server: apachephp
    servername: drupal8.local www.drupal8.local 192.168.33.99
    timezone: America/New_York
  vars_files:
    - vars/mysql.yml
    - vars/common.yml
    - [ "vars/apachephp.yml", "vars/ws_defaults.yml" ]
  roles:
    - init
    - php5-cli
    - apache
    - php5
    - mysql
    - composer
    - phpcommon
    - app

Using the Box

Before using the box, you have to install Vagrant and Virtualbox on your machine. Then clone or download the files from from github: https://github.com/omerida/drupal8-vm. In the directory where the files are use vagrant up to start the machine. The default URL is http://drupal8.dev/ To access it, add the following line to your hosts file:

192.168.33.10   drupal8.dev

Once the box is booted, open a browser and go to “http://drupal8.dev” and you should see the Drupal 8 installation wizard. d8-install

What’s next?

This gives you a very basic machine to work on. From here, you could do a number of things:

  • Add the dotdeb.org repository to get newer versions of PHP and MySQL.
  • Figure out how to add drush to the guest system
  • Further automate the basic Drupal installation
  • See how to install contrib modules to the site.

If you can script it, you can automate it.


Oscar still remembers downloading an early version of the Apache HTTP server at the end of 1995, and promptly asking "Ok, what's this good for?" He started learning PHP in 2000 and hasn't stopped since. He's worked with Drupal, WordPress, Zend Framework, and bespoke PHP, to name a few. Follow him on Google+.
Tags: , ,
 

Responses and Pingbacks

For drush, composer is the best. You can use a variable on ansible, and change the version of drush very easily from a yaml file.
There is a popular VM for Drupal 8 (supports drupal 7 too) that uses ansible. I tested it with Ubuntu only, but the creator is using CentOS with it. It supports only Apache at the moment. If you want to have a look : https://github.com/geerlingguy/drupal-vm

Leave a comment

Use the form below to leave a comment: