Building a development environment from a production website with Vagrant and VirtualBox

When it comes to local development environments, in a lot of cases Mugo uses VirtualBox images and manages them with Vagrant. These environments are sometimes created after the production environment has been set up. To make a local development environment as similar to production as possible, one approach is to actually copy the production server.

VirtualBox is a virtualization product that runs on all major operating systems. For example, on my Mac OS laptop I can create a virtual machine running Red Hat Enterprise Linux with all project-required services like PHP, MySQL, Solr, and so on.

Vagrant allows me to configure, download, start, and stop a VirtualBox image. It is also responsible for sharing the project source code between the virtual machine and the host operating system. For example, on my Mac OS laptop I use PhpStorm to work with the project source code. The source code is shared via NFS with the virtual machine, so that all of the code changes I make in PhpStorm directly affect the local development environment.

Copying from production to the local environment

There are many ways to create a local virtual machine setup. For example, you can use Ansible to configure the virtual machine as described in another blog post. Or, you can use only VirtualBox and build the virtual machine manually. Another possibility, as I will describe in this post, is to convert the raw contents of the production or staging hard drive into a VirtualBox image file. Basically, you build a copy of your production or testing environment containing all services, OS configurations, data, and source code.

The basic idea is to use the linux tool dd to capture the raw hard-drive content into a file. Then, the VBoxManage tool, which comes with VirtualBox, turns the raw image into a VirtualBox image.

As you can see in the script, this is quite involved, as it does the following:

Stop all services to reduce the activity on the hard drive; this avoids errors in the dd image. This takes the site down temporarily of course, so you usually have to do this from the staging or testing environment.

Check the image for errors and fix those, as dd sometimes leaves some lost inodes

Set a specific UUID for the hard drive, to ensure that it matches your VirtualBox configuration

Make sure you have an additional hard drive to create the virtual machine

Having an exact copy of the production or testing environment for local development is great, in order to reduce any surprises when it's time to deploy your work. However, there are some challenges. One challenge is if you have a scheduled script that should be run on the production environment only. That's why the configuration or system scripts sometimes need to know the environment they are in. Here is an example that checks for the presence of VirtualBox:

Editing site code

Usually, we use Vagrant to mount the source code from the host operating system to the virtual machine. You can also do the opposite: set up an NFS server on the virtual machine and tell Vagrant to mount the share to the host OS. This unusual setup has some pros and cons:

Pro: Performance is much better when the code base is located directly on the virtual machine.

Pro: It is more straightforward to have Windows mount an NFS location than to have a Windows NFS server.

Con: The source code is only available once the virtual machine is started. Sometimes you only want to implement simple code changes and it is a bit overkill to start the virtual machine for that. You should consider to check out another instance of the source code on your host OS for these types of code changes.

Con: Accessing the code base over NFS lowers performance for full text search or code synchronization with a remote code repository. This can be mitigated if you use an editor such as PhpStorm that creates its own search index.

Here is an example Vagrant configuration file to manage the virtual machine, including the mount from the virtual machine to the host OS: