WordPress configuration management

This is the 4th post in a series of developing for WordPress in a DevOps friendly way. The other articles:

  1. Introduction to WordPress and DevOps
  2. Developing with WordPress and Vagrant
  3. Grunt Automation for WordPress developer
  4. WordPress configuration management

In the previous posts in this series we’ve been looking at how to work with Vagrant and WordPress and how to automate setup work using Grunt and WP-CLI. In this posts, we’ll look a little bit on how we can transfer various settings between the WordPress database and into text files in the source code tree. Because as soon as we have the settings in files, we can easily transfer those settings to a target system such as a staging environment or the live site.

There’s a Git repository available with code for this post here: https://github.com/eriktorsner/wpconfigurationmanagement I suggest you clone or download the code to your development computer to make it easier to follow along.

WordPress settings

A Setting is any of the small or large things you change in the Settings menu in the WordPress admin area. The number of blog posts shown on the first page is a setting and so is the site title and the default date format.

Settings
Some of the well known settings from the WordPress admin area

 

WordPress uses the database to store settings into a table named wp_options (at least as long as you are using the standard wp_ prefix). Most of the settings that a core WordPress installation will put into the wp_options table are simple scalar values, a string or a numeric value. But some of the settings consists of larger more complex structs like an array or even arrays containing objects containing arrays. The internal WordPress code makes sure that pretty much anything you can represent in a PHP variable can be stored as a setting. If needed, WordPress uses the native PHP function serialize() to convert any given variable to a text representation suitable for database storage and then unserialize() to convert it back when needed.

Serializing

The concept of taking a complex structure and transforming it into a text representation is called seriallization, so no wonder the PHP functions are named as they are. In our ambitions to automate the setup of WordPress, we want to serialize some settings to a text file that we can keep in our source code repository. When we first install a development version of our WordPress site in a new environment, or when we want to deploy it to another environment, we want to take that text file with serialized settings and update the database. To do this we will continue to build on the WordPress skeleton from the previous posts, you’ll find it in the Github repository for this post. To get started with this code repository, please refer to the first post to learn a little bit about Vagrant and how we’re using it. A few notes:

  • This repo uses an evolved version of the Vagrantfile. Only the rows you need to change are present, everything else is moved in to a file in the vagrant/ sub folder.
  • No need to change anytning inside the vagrant/ sub folder, everything it’s taken care of during provisioning.

 We’re going to talk about two different approaches for managing settings in a text file. The first approach is using Gruntfile.js itself, the other approach uses the free plugin WP-CFM.

Keeping settings in Gruntfile.js

The most straight forward way would be to use Gruntfile and Wp-cli. The settings themselves will be in the form of Wp-cli statements that will be automatically inserted into the target WordPress installation when the Grunt task wp-setup is executed.


grunt.registerTask('wp-setup', '', function() {
	ls = getLocalsettings();
	wpcmd = 'wp --path=' + ls.wppath + ' --allow-root ';
	
	// some standard plugins
	stdplugins = ['google-analyticator', 'wp-cfm'];
	for(i=0;i<stdplugins.length;i++) {
		name = stdplugins[i];		
		shell.exec(wpcmd + 'plugin install --activate ' + name);
	}

	shell.exec(wpcmd + 'option update blogname "New blog title"');
	shell.exec(wpcmd + 'option update blogdescription "experimental tagline"');
	shell.exec(wpcmd + 'option update posts_per_page "20"');

})

The three highlighted rows will update the Site title (blogname), the tag line (blogdescription) and the ‘Blog pages show at most’ setting (posts_per_page) that are found in WordPress Admin. This is a very manual form of serializing settings to disk and it’s easy to get started with. If you only have a few of them that you need to set, this approach will work but it has a few downsides.

Obviously, the manual work involved in writing the wp-cli statements in your Grunt file is not very optimal. Easy to forget individual settings, easy to lose the overview etc. The other downside is that changes you make in WordPress admin has no way of automatically find their way into the Gruntfile. You’re in for a lot of manual work. But there is another way.

WP-CFM

WP-CFM is a free plugin available in the WordPress plugin repository. It’s name stands for WordPress Configuration Management and it does exactly that: Configuration Management. WP-CFM uses a concept call bundels. A bundle is a group of individual WordPress settings. WP-CFM can Push a bundle to file, meaning that it will read the value of each of the settings in the bundle from the database and store them in a file. And later, WP-CFM can Pull that file back in and restore those values in the database.

In the Gruntfile above I took the liberty of installing and activating wp-cfm in the WordPress installation in the Vagrant box, so if you’re following along you should already have it in WordPress. This plugin adds a menu item under settings named WP-CFM. The main WP-CFM screen looks like this:

WP-CFM admin screen

We want to create a bundle with the same three setting that we handled in the Grunt task above. So we’ll go ahead and click ‘Add Bundle’, name it ‘settings’ and select the individual settings items we need:

Creating a new bundle in WP-CFM
Creating a new bundle in WP-CFM (note, the posts_per_page setting is under the fold in this image)

After the bundle is created and saved, we can click ‘Push’ to store those three settings to disk. You should end up with a text file in /vagrant/www/wordpress-default/wp-content/config named settings.json:

{
    "blogdescription": "experimental tagline",
    "blogname": "New blog title",
    "posts_per_page": "20",
    ".label": "settings";
}

As you can see, WP-CFM uses a JSON file to store the individual values and stores the file in a predictable location. For fun, we can change the “blogname” setting inside this file and try the Pull button (you probably will need to reload the page for the Pull button to become active). Once the updated settings has been pulled into the database and you’ve reloaded the page, you should see that whatever value you selected for “blogname” now is in the page title.

A little automation

The one great thing with WP-CFM that I didn’t mention yet is that it was written with support for Wp-cli right out of the box. WP-CFM adds a command verb to Wp-cli named ‘config’ with sub commands push and pull. We just need to call these two commands from our Gruntfile to automate things. As usual,  a little bit of plumbing is also needed as well, best explained with code, so let’s have a look at the two new Grunt tasks that we’ve added for this post:


grunt.registerTask('wp-export', '', function() {
	ls = getLocalsettings();
	wpcmd = 'wp --path=' + ls.wppath + ' --allow-root ';
	pwd = shell.pwd();

	shell.mkdir('-p', pwd + '/config');

	// push settings from DB to file
	src = ls.wppath + '/wp-content/config/settings.json';
	trg = pwd + '/config/settings.json';
	shell.exec(wpcmd + 'config push settings');
	shell.cp('-f', src, trg);
});

grunt.registerTask('wp-import', '', function() {
	ls = getLocalsettings();
	wpcmd = 'wp --path=' + ls.wppath + ' --allow-root ';
	pwd = shell.pwd();

	shell.mkdir('-p', ls.wppath + '/wp-content/config');
	
	src = pwd + '/config/settings.json';
	trg = ls.wppath + '/wp-content/config/settings.json';
	shell.cp('-f', src, trg);
	shell.exec(wpcmd + 'config pull settings');
});

  • Line 53, define the task wp-export
  • Line 58, create the /vagrant/config folder unless it already exists
  • Line 63, run the wp-cli command ‘config push’ for the bundle named ‘settings’
  • Line 64, copy the settings file into our local folder /vagrant/config where it will be under source code control

 

  • Line 67, define the taks wp-import
  • Line 72, create the folder www/wordpress-default/wp-content/config unless it already exists
  • Line 76, copy the settings.json file from the project folder into the correct folder in the WordPress installation (where WP-CFM will expect to find it)
  • Line 77, run the wp-cli command ‘config pull’ for the bundle named settings so that each settings is pulled from the file into the database

Since the WP-CFM plugin was build for automation from the start, our work is reduced to managing the settings file so that we can keep in under source code control. With these two Grunt tasks, we’ve now automated the process for storing WordPress settings in the source code control system.

A few pitfalls

Using WP-CFM together with Grunt and wp-cli takes us a long way in terms of creating a fully automated process for managing WordPress.  However, this process isn’t really perfect yet. There are a few issues to look out for when it comes to WP-CFM:

  • Some settings might store the absolute URL for a post or page on the WordPress installation. If that setting is pulled from disk to the database unchanged, the live site might end up with URL references to the development version of the site
  • Some settings contains references to a page, a post or a menu item using the internal database id and the database ID might differ between the development version and the production version.

These two issues as well as the challenge of moving actual content (pages, images etc) from development to production is going to be covered in future posts in this series. So stay tuned!

 

WordPress DevOps – The book

I’ve written an ebook on this subject. Released in September this year on Leanpub.com. Expect a 100+ tightly written pages where we walk through the creation of the skeleton of a WordPress based Saas application, connected to Stripe and Paypal with a working deployment process that takes content into account. Just add your billion dollar idea. Jump on over to Leanpub to get your copy.

WordPress DevOps - Strategies for developing and deploying with WordPress
WordPress DevOps – Strategies for developing and deploying with WordPress

 

 

 

 

 

 

 

[wysija_form id=”3″]

WordPress DevOps – The book

Today the eBook on WordPress and DevOps was released.  Go directly to Leanpub and get your copy.

WordPress DevOps
WordPress DevOps – The book

What is it about?

The challenge

When dealing with WordPress sites in the long run, it’s easy to end up in trouble. Have you ever upgrading a plugin just to find that the upgraded version ruined your site? Have you ever hesitated to upgrade WordPress core since you are not sure about any nasty side effects? If so, you are in good company. Lots of WordPress developers and site administrators find themselves in this situation daily.

The common advice for this problem is to take a backup of the entire site, restore the backup on another server and make all upgrades and other changes on the alternate site. But then what? If you just copy all those changes back together with the database to the live site, you’ll risk losing content that was added while you were working. Any new posts, comments or orders that came is will simply be gone. So you can chose between accepting that potential loss or transfer the changes back manually once you’ve figured them out. Sometimes it might be easy, but it will often be messy process.

At the end, you’re going to ask yourself if that messy process is really worth your time.

A solution

In this book, I walk the reader through a solution that is based on the concept of trying to separate application (code, menus, pages etc.) from content and a method creating your own tools to manage that separation. The book is a walk through of the process of setting up a reasonably complex WordPress membership site where the separation between application and content becomes clear. Covering how to start using modern tools like Vagrant and Git to manage a safe development environment, how to deploy safely using Rocketeer, a dedicated deployment tool and how to structure the WordPress application so that it’s easy to develop locally and deploy safely.

Get IT? Get IT!

This book is currently sold via Leanpub where you get to decide the price yourself (well almost anyway). As with all their titles, you can download the book as a pdf, mobi or epub format, so you can read it on pretty much any computer or eBook reader software. The book comes with lots of code that is available to readers via a Github, so you’re not only learning, you’ll also have the code to get your WordPress DevOps process started quickly.

Click the cover image below or sign up for the newsletter in the form below and receive a 25% discount code. Valid until October 31st 2015.

WordPress DevOps
WordPress DevOps – The book

Note. As a Leanpub author I’m specifying a minimum and a recommended price for you to pay. On top of that Leanpub adds VAT depending on your location. With the discount code, the minimum price is discounted by 25%

[wysija_form id=”3″]

Grunt Automation for WordPress developers

This is the third article in a series of developing for WordPress in a DevOps friendly way. The previous articles:

  1. Introduction to WordPress and DevOps
  2. Developing with WordPress and Vagrant
  3. Grunt Automation for WordPress developers
  4. WordPress configuration management

In the previous two posts we’ve had a look at the various tools we need to create an automated workflow for developing and a little bit about how Vagrant can be used to create a better development environment. We’ve also briefly touched on using Grunt and wp-cli to automate setting up WordPress inside the environment. In this post we’ll dive deeper into how to use Grunt to automate even more of the WordPress setup.

There’s a Git repository available with code for this post here: https://github.com/eriktorsner/gruntautomationforwp I suggest you clone or download the code to your development computer to make it easier to follow along.

What’s our goal?

In short. We want to run a single command at the command line to install WordPress, all our wanted plugins and other vital pieces of configuration. The end goal is to automate it to the extent that it can be part of a fully automated, non-interactive, deployment process.

Looking back at the first post in this series I talked a bit about DevOps and how it’s a bit of a challenge to make WordPress a good fit for it. Automation is one of the cornerstones within DevOps and historically WordPress has been more focused on getting up and running quick than on supporting an automated workflow.

Well, that changed entirely when wp-cli came onto the scene a few years back. Wp-cli stands for WordPress command line interface and is a project that aims to enable automation of WordPress management. Wp-cli makes it possible to automate installation, setup, theme and plugin installations and a lot of other common WordPress management tasks like modify settings or even add pages and posts.

The other part of the automation work will be carried out by Grunt. Grunt is a “modern JavaScript task runner” and allows us to create tasks that can be executed from the command line. So we can create a task “wp-install” that uses wp-cli to install WordPress and run that task from the command line using a simple “grunt wp-install”. The most common use case for Grunt is to run things like css and javascript minification or compile SASS file to css. But we’ll use Grunt mainly as a task runner for DevOps related tasks. That doesn’t stop you from using Grunt for those other things as well which may be a very good idea for your project.

Creating the environment

In the previous post, we covered how to get started with Vagrant. To follow along in this post I’m assuming that you’ve read that post and have installed the prerequisites for running Vagrant on your development computer. I’ve made a separate Github repository available for this post, so from now on when I’m talking about specific files, I’m referring to the ones you can find in the git repo at https://github.com/eriktorsner/gruntautomationforwp. If you have any problems following these steps, be sure to read up on the previous post and post any questions in the comments below if you’re still having issues.

A quick checklist to get you started with this Vagrant box

  1. Edit Vagrantfile (hostname, dns names and ip-numner) to fit in your environment
  2. copy localsettings.json.template to localsettings.json
  3. Run “vagrant up” to initialize the new machine”
  4. Go to folder /vagrant inside the virtual machine and run “npm install”

Wp-cli + Grunt

To show what Wp-cli can do in terms of automation, we’ll use it to perform the following tasks:

  1. Install WordPress
  2. Install and activate a few plugins from the official WordPress repo
  3. Change a few settings

As we’ll be doing this by automating wp-cli via Grunt. Let’s have a look at the important parts of the Grunt file that comes with this post (see the top of the post for information on how to get it). The first thing to notice is on 32 where we define the function getLocalSettings, a simple helper function.


function getLocalsettings(test) { 
    ls = grunt.file.readJSON('localsettings.json'); 
    if(ls.wppath === undefined) ls.wppath = shell.pwd() + '/www/wordpress-default'; 
    return ls; 
}

We’ll use this function in each of our Grunt tasks that deals with wp-cli so that we can get the parameters we define in localsettings.json into action. Let’s look at the settings file to get a hunch of what kind of parameters we’re including


{
    "environment": "development",
    "url": "www.gruntautomationforwp.local",
    "dbhost": "localhost",
    "dbname": "wordpress",
    "dbuser": "wordpress",
    "dbpass": "wordpress",
    "wpuser": "admin",
    "wppass": "admin",
    "wppath": "/vagrant/www/wordpress-default"
}

 

The idea is to have anything that is specific for this specific machine should be a parameter in this file. And the point of having settings in a json format is that json can be easily accessed both from javascript code like in the Gruntfile and in PHP code as well.

Let’s look at the first task defined, the default task:


grunt.registerTask('default', 'Log some stuff.', function() {
    ls = getLocalsettings();
    grunt.log.write('localsettings successfully read URL=' + ls.url).ok();
});

It will simply read the settings file and output the URL parameter from it, so it’s a simple test. Let’s try it within the Vagrant machine:

$ cd /vagrant
$ grunt
Running "default" task
localsettings successfully read URL=www.gruntautomationforwp.localOK

Done, without errors.

The next task to look at is the wp-install task, it’s a bit more interesting:

 /*
 * Installing WP
 */
 grunt.registerTask('wp-install', '', function() {
     ls = getLocalsettings();
     wpcmd = 'wp --path=' + ls.wppath + ' --allow-root ';

     shell.mkdir('-p', ls.wppath);

     if(!shell.test('-e', ls.wppath + '/wp-config.php')) {
         shell.exec(wpcmd + 'core download --force');
         shell.exec(wpcmd + 'core config --dbname=' + ls.dbname + ' --   dbuser=' + ls.dbuser + ' --dbpass=' + ls.dbpass + ' --quiet');
         shell.exec(wpcmd + 'core install --url=' + ls.url + ' --title="WordPress App" --admin_name=' + ls.wpuser + ' --admin_email="admin@local.dev" --admin_password="' + ls.wppass + '"');
     } else {
         grunt.log.write('Wordpress is already installed').ok();
     }
 });
  • Line 18 is just loading the localsettings as we saw above
  • Line 19 creates the base string for the wp-cli command. Note that we’re adding the switch –allow-root since this task is likely to be executed by root in a different environment like production. We’re also adding the –path switch which will instruct wp-cli to install WordPress in a sub folder.
  • In line 23 we’re checking if WordPress is already installed or not.
  • Lines 24 to 26 are executing the wp-cli commands “core download”, “core config” and “core install”.

There are a few interesting things to note. The first is obviously that after running this task we’re going to have a fully functioning WordPress installation in a sub folder. All parameters we needed are kept in a separate file which is fundamentally good for our efforts to make this a fully automated WordPress install. We’ve also managed to install WordPress in a sub folder that is explicitly kept out of source code control.

The reason for that is that WordPress in not our code, it’s a depencency to us. We want to avoid adding dependencies in our source code tree (look inside .gitignore, we’re explicitly ignoring the www sub folder) for several reasons. But the most important reason is not size or bloat, it’s the ability to handle upgrades well. WordPress and it’s extensions are upgraded frequently with major and minor upgrades. If you add all the source code for WordPress, themes and plugins into your own source code tree, you will be stuck with the task of upgrading them once new versions arrive, and they do quite often.

A clean separation between your own code and the dependencies means that you can easily test your code with the newest versions of each dependency. If your code breaks as a result of upgrading one of the third party plugins, the clean separation and automated setup makes it super easy to test and fix any such problems before you upgrade anything in production. That’s a big deal.

So, back to our example, let’s run the wp-install task:

$ grunt wp-install
Running "wp-install" task
Downloading WordPress 4.3.1 (en_US)...
Success: WordPress downloaded.
sh: 1: /usr/sbin/sendmail: not found
Success: WordPress installed successfully.

Adding more dependencies

Obviously, we’re going to need more dependencies. Let’s add a few plugins from the WordPress plugin repository. This is done with the wp-cli command “plugin install”. Let’s look at the next task in Gruntfile.js:

/*
* Setting up WP
* 
*/
grunt.registerTask('wp-setup', '', function() {
    ls = getLocalsettings();
    wpcmd = 'wp --path=' + ls.wppath + ' --allow-root ';
	
    // some standard plugins
    stdplugins = ['if-menu', 'baw-login-logout-menu','google-analyticator'];
    for(i=0;i<stdplugins.length;i++) {
        name = stdplugins[i];		
        shell.exec(wpcmd + 'plugin install --activate ' + name);
    }
})
  • Lines 37-38 are similar to the wp-install task
  • Line 41 sets up an array of plugins we want to install
  • Lines 42-45 iterates that array and creates a wp-cli command that installs and activates all the plugins in the array.

So no more manual plugin installations in the WordPress admin area! Let’s run the Grunt wp-setup task:

$ grunt wp-setup
Running "wp-setup" task
Installing If Menu (0.3)
Downloading install package from https://downloads.wordpress.org/plugin/if-menu.zip...
Unpacking the package...
Installing the plugin...
Plugin installed successfully.
Success: Translations updates are not needed for the 'English (US)' locale.
Activating 'if-menu'...
Success: Plugin 'if-menu' activated.
Installing Login Logout Menu (1.3.3)
Downloading install package from https://downloads.wordpress.org/plugin/baw-login-logout-menu.zip...
Unpacking the package...
Installing the plugin...
Plugin installed successfully.
Success: Translations updates are not needed for the 'English (US)' locale.
Activating 'baw-login-logout-menu'...
Success: Plugin 'baw-login-logout-menu' activated.
Installing Google Analyticator (6.4.9.6)
Downloading install package from https://downloads.wordpress.org/plugin/google-analyticator.6.4.9.6.zip...
Unpacking the package...
Installing the plugin...
Plugin installed successfully.
Success: Translations updates are not needed for the 'English (US)' locale.
Activating 'google-analyticator'...
Success: Plugin 'google-analyticator' activated.

Done, without errors.

Working with settings

The last part I’m going to cover in this post is a little bit on how to manipulate WordPress settings. Wp-cli is not the only option we have to get settings from a text file (code) into a live WordPress installation, but since wp-cli can do this, let’s have a look at how.

Most settings in WordPress are stored in a table named wp_options (assuming you’ve kept the standard “wp_” table name prefix). In order to change any of those settings via wp-cli, we first need to figure out what the various settings are called. Wp-cli have a sub command “option” that lets us list, add, delete or modify settings. For instance, if we want to change the settings “Site title” and “Tagline” we could use wp-cli to list all options and search for the options we want to find. In the wp-install task, we set the string “WordPress App” as the title, lets search for it:

$ cd /vagrant/www/wordpress-default/
$ wp option list | grep 'WordPress App'
blogname	WordPress App

Ok, there’s only one single row in the options table with that string, so we can safely assume that the option called “blogname” corresponds to Site title. Let’s look for the tagline, we haven’t changed it yet in our test installation, so it should still read “Just another WordPress site”:

$ wp option list | grep 'ust another WordPress site'
blogdescription	Just another WordPress site

Right. The parameter tagline that we can control in the WordPress admin is found in the option named “blogdescription”.

Knowing what the options are called makes it possible to set them via wp-cli. We can add a few lines to the wp-setup task:

    shell.exec(wpcmd + 'option update blogname "Another title"');
    shell.exec(wpcmd + 'option update blogdescription "experimental tagline");

Running the wp-setup task again, we should now see:

$ grunt wp-setup
Running "wp-setup" task
Warning: if-menu: Plugin already installed.
Activating 'if-menu'...
Warning: Plugin 'if-menu' is already active.
Warning: baw-login-logout-menu: Plugin already installed.
Activating 'baw-login-logout-menu'...
Warning: Plugin 'baw-login-logout-menu' is already active.
Warning: google-analyticator: Plugin already installed.
Activating 'google-analyticator'...
Warning: Plugin 'google-analyticator' is already active.
Success: Updated 'blogname' option.
Success: Updated 'blogdescription' option.

Done, without errors.

Note that wp-cli won’t attempt to reinstall the plugins that are already activated but instead just sends a warning saying that it’s already there. The last few lines tells us that the blogname and blogdescription settings are now updated to their new values. Mission accomplished.

 

Summary

In this post, we’ve taken another few steps towards gettings WordPress under our control. We’ve discussed the reasons why we want to treat WordPress itself as well as any third party extensions as dependencies rather than a part of our own application. Not in the sense that the code we develop would work well without WordPress and the plugins, but because we need to keep them out of our code base for upgrading and testing reasons.

In future installments in this series, we’ll dive into dealing with content and try to find ways to make WordPress separate content and content. If that sounds weird or if you’re just the curious anyway, stay tuned for the next episode. In the mean time, share insights, questions or other feedback in the comments below.

WordPress DevOps – The book

I’ve written an ebook on this subject. Released in September this year on Leanpub.com. Expect a 100+ tightly written pages where we walk through the creation of the skeleton of a WordPress based Saas application, connected to Stripe and Paypal with a working deployment process that takes content into account. Just add your billion dollar idea. Jump on over to Leanpub to get your copy.

WordPress DevOps - Strategies for developing and deploying with WordPress
WordPress DevOps – Strategies for developing and deploying with WordPress

 

 

 

 

 

 

 

[wysija_form id=”3″]

Developing with WordPress and Vagrant

This is the second post in a series of developing for WordPress in a DevOps friendly way. The other articles:

  1. Introduction to WordPress and DevOps
  2. Developing with WordPress and Vagrant
  3. Grunt Automation for WordPress developers
  4. WordPress configuration management

Lets recap a bit to last post in this series. Vagrant is a piece of software that will help you automate the creation of Virtual Machines right on your development computer. The benefits of running your WordPress project inside a Vagrant machine are that (1) you can use the same software stack of operating system, web server and database as you will use in production and (2) you can make changes to the development environment without affecting the rest of your computer or any other projects. Lastly (3) it’s super easy to make sure that all developers working on the same project actually has the exact same environment.

In this post we will get a bit practical and demonstrate how Vagrant works. We will set up a WordPress installation inside a Vagrant machine and then surf to it from your development computer and we will automate as much of the WordPress installation as possible. In fact, it’s so automated out of the box that you will only need to type five (5) commands to get your WordPress install up and running. We’ll also touch briefly on the tools Grunt and wp-cli, but more in depth articles on those tools will follow soon.

Preparing

Before we can do anything else, we need to get Vagrant and a Virtual Machine manager installed on our development computer. This step depends on the OS on your machine and as the Vagrant documentation says, it’s extremely easy. Head over to their downloads page and install it using standard procedures on your OS.

The same goes for the Virtual Machine Manager. Vagrant supports VirtualBox and VM-Ware as well as a few other possible backends. I’m a long big fan of VirtualBox so that’s what I recommend. Head on over to the VirtualBox downloads page and get the version that’s right for your computer. Install it using standard procedures on your OS.

We also want to install a plugin to Vagrant called host-updater. This plugin will automatically rewrite the hosts file (/etc/hosts) on the host machine, that makes it so much easier to surf to the WordPress installation later on and keep. At the command prompt of your computer type:

$ vagrant plugin install vagrant-hostsupdater

Setting up a remote repository

Clone or copy my Get repository for this blog post, https://github.com/eriktorsner/wordpressvagrant, into a folder on your computer. From now on, we’lll refer to that folder as the project folder. I suggest your start your own remote Git repository (on github or elsewhere) so that you get your project under source code control right from the start. It’s good development practice.

The included files.

As you can see, there are only a handful of files in the code you’ve just copied. Let’s talk about what they do:

  1. Vagrantfile This file is the main Vagrant configuration file. It defines the virtual machine that we’ll soon fire up. If instructs Vagrant to create a machine with a specific hostname, a specific amount or RAM and disk, what IP-number to use and a few other things. At the top of this file, there are 4 lines of code that needs to be changed to suit your environment, but other than that, you should be able to use this file as is. One of the most important parameters that is defined in this file is “config.vm.box” that tells Vagrant what base image to start with. We’re using “ubunty/trusty64” which gives us a bare bones Ubuntu 64 bit operating system to start with.
  2. Subfolder vagrant. This subfolder contains some additional settings for Vagrant that is uses during the provisioning phase. We’ll talk more about provisioning further down, but basically it’s a script that is executed the first time we start the virtual machine and that installs “everything else” which in our case means the nginx webserver, MySQL database server, PHP and a bunch of other useful tools.
  3. package.json is the settings file for the Node Package Manager (NPM). We use NPM to install Grunt and some of it’s dependencies.
  4. Gruntfile.js is the settings file for the Grunt automation tool. We’ll talk more about Grunt in a later episode, right now it’s enough to know that Grunt can be used to automate things and that we’ll use it to automate WordPress installations.
  5. .gitignore is simply a file that tells Git what files and folders we want to keep out of version control
  6. localsettings.json.template In our approach to WordPress we want to automate as much as possible and to do that, we need a place to store things that are unique to this particular environment. Since this file should never be added to Git, I’ve included a template, not the actual file. Any setting that will differ from this development environment we’re currently creating and the live production environment should be captures in this file. In this template file, we have things like URL, path to WordPress, WordPress passwords etc. The parameters in the template happen to nicely align to most default values defined in Vagrantfile and provisioning.

Starting the virtual machine

Before we can start the Vagrant machine for the first time. Open Vagrant file and make sure lines 3-6 have sensible values. Hostname, devdns and testdns should have values that makes sense for your project name and ipnumber should be a unique ip number that is not already used by another virtual machine on your computer.

# -*- mode: ruby -*-
# vi: set ft=ruby :
hostname = 'wpvagrant'
ipnumber = '192.168.50.33'
devdns = 'www.wpvagrant.local'
testdns = 'test.wpvagrant.local'

Once you’ve made those changes, fire up your Vagrant box with this simple command:

$ vagrant up

Now is a good time to grab a cup of coffee. Vagrant will download and install a lot of things. On my computer this process normally takes 5-8 minutes, but it will vary depending on network speed and your computers performance.

Working inside the virtual machine

Once Vagrant has finished it’s setup process we’ll log into the command line shell of the virtual machine. Type the command vagrant ssh and you should be greeted with something like this:

$ vagrant ssh
Welcome to Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-46-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

 System information disabled due to load higher than 1.0

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.

vagrant@wpvagrant:~$ 

An important feature of Vagrant is that it keeps folders on your development computer in sync with a special folder inside the virtual machine. By default, this folder is named vagrant and is located at the root of the file system. Go to that folder and check out the contents, it should match exactly what you see in the project folder on your development computer

vagrant@wpvagrant:~$ cd /vagrant
vagrant@wpvagrant:/vagrant$ ls -alg
total 52
drwxrwxr-x 1 vagrant 4096 Sep 18 10:07 .
drwxr-xr-x 24 root 4096 Sep 18 10:05 ..
drwxrwxr-x 1 vagrant 4096 Sep 17 18:12 .git
-rw-rw-r-- 1 vagrant 216 Sep 18 09:46 .gitignore
drwxrwxr-x 1 vagrant 4096 Sep 18 10:01 .vagrant
-rw-rw-r-- 1 vagrant 1461 Sep 18 10:07 Gruntfile.js
-rw-rw-r-- 1 vagrant 1079 Sep 17 18:12 LICENSE
-rw-rw-r-- 1 vagrant 19 Sep 17 18:12 README.md
-rw-rw-r-- 1 vagrant 3995 Sep 18 09:40 Vagrantfile
-rw-rw-r-- 1 vagrant 405 Sep 18 09:11 localsettings.json.template
-rw-rw-r-- 1 vagrant 354 Sep 17 18:52 package.json
drwxrwxr-x 1 vagrant 4096 Feb 4 2015 vagrant
drwxrwxr-x 1 vagrant 4096 Sep 18 10:08 www

 

Installing WordPress

We are only a few commands away from installing WordPress. First we’ll copy / renamelocalsettings.json.template so that we have a correctly named localsettings file.

$ cp localsettings.json.template localsettings.json

As I wrote above, no actual changes are needed inside this file as long. Next, we’ll use npm to get all the dependencies for Grunt.

$ npm install

Npm takes a few seconds and when it’s finished you should see that you have a new sub folder node_modules in your project folder. And lastly, we’ll use Grunt to install WordPress using a custom Grunt task:

$ grunt wp-install

And that’s it. WordPress should be ready to use. Test it by using a web browser on your desktop and type in the address to your development machine. The default is: http://www.wpvagrant.local (but you’ve might have changed it in the Vagrantfile).

Summary

In this article, we’ve looked at how easy Vagrant can be made part of your development environment, as a side effect you’ve also saw a glimpse of how WordPress installs can be automated using wp-cli and Grunt (more on that in a later post). Since Vagrant has grown in popularity there are many alternative Vagrant default configurations you can use for WordPress development. The one I’ve share is this article is geared towards developing web sites with WordPress, but there are others that are organized to be more suitable for Theme or Plugin development. To mention a few:

  • Varying Vagrant Vagrants (https://github.com/Varying-Vagrant-Vagrants/VVV) is the first I encountered that is focused on WordPress. My configuration is based on this.
  • VCCW (http://vccw.cc/) is another good option. One of the benefits is that it uses Chef for provisioning rather than a shell script as mine and VVV does.
  • dominikzogg/vagrant-php (https://github.com/dominikzogg/vagrant-php) is a generic PHP development environment that supports WordPress among other things. I find this very interesting because it makes it easy to try your application on different versions of PHP, including PHP 7 and HHVM

In the next post in this series, we’ll dive deeper into automating the WordPress installation even further. We’ll look at how to get plugins, themes and settings in place using code rather than manual configuration in the WordPress admin area.

Until then, over to You, let me know what you think in the comments.

WordPress DevOps – The book

I’ve written an ebook on this subject. Released in September this year on Leanpub.com. Expect a 100+ tightly written pages where we walk through the creation of the skeleton of a WordPress based Saas application, connected to Stripe and Paypal with a working deployment process that takes content into account. Just add your billion dollar idea. Jump on over to Leanpub to get your copy.

WordPress DevOps - Strategies for developing and deploying with WordPress
WordPress DevOps – Strategies for developing and deploying with WordPress

 

 

 

 

 

 

 

[wysija_form id=”3″]

Introduction to WordPress and DevOps

This is the first article in a series of developing for WordPress in a DevOps friendly way. The other articles:

  1. Introduction to WordPress and DevOps
  2. Developing with WordPress and Vagrant
  3. Grunt Automation for WordPress developers
  4. WordPress configuration management

In this post, we’ll talk about what DevOps means to WordPress developers.  Can DevOps deal with WordPress and perhaps more important, can the WordPress community deal with DevOps?

So what is DevOps? Wikipedia describes DevOps as a development method that emphasizes collaboration, integration and automation between software development teams and other IT professionals. To understand what that means in practical terms it’s easier to look back at how IT used to work at many companies. There’d be two teams of technical people, one team would focus on developing web stuff or internal applications. The other team would focus on maintaining servers, network infrastructure, look after backups among other things, commonly referred to as operasions. The communication between them was often kept at a “need to know basis” and blame storming would be common. Not everywhere, but often enough for problems to arise.

The introduction of DevOps as a concept was first and foremost a mindset change. With better collaboration between development and operations came better understanding of how each part of the equation works. Better understanding also quickly led to better internal processes and soon thereafter, better tools and more automation. Today the term DevOps often means a mix of these things. DevOps can mean the process or method of getting internally developed software into production. DevOps can sometimes refer to a set of tools to help that work. Or in some places DevOps is simply the new name for the part of IT department that deals with these issues.

In the the context of WordPress, we need to think of DevOps primarily as automation. A large part of the work we do in WordPress is within the system. Write blog posts and publish them is the perfect example of that. As long as the WordPress installation is backed up on a regular basis, that’s fine. But software developers also work on the system. Expanding WordPress with new plugins, installing eCommerce addons, developing a custom theme etc. At some point, those changes needs to be pushed from a developers environment to the production environment, also known as deployment.

 

If we do that manually using ftp to move files and the WordPress admin area to install plugins by hand, we’re pretty far from an automated workflow, we’d call it manual deployment. But if we can lift ourselves so that deploying a new version of a WordPress site into production is fully automated, well, then we’re working in the spirit of DevOps.

 

But it’s not enough just to automate and be done. A good deployment process will only deploy code that passes some quality tests. It will allow for some sort of rollback if we discover problems. And it is designed so that we never ever lose data as a result of a deploy. The relevant question is how do we get from a manual deployment workflow to a fully automated safe workflow with quality assurance?

I find that when someone's taking time to do something right in the present, they're a perfectionist with no ability to prioritize, whereas when someone took time to do something right in the past, they're a master artisan of great foresight.
The general problem

Automation requires upfront work

Let’s just get this out of the way first. There is no silver bullet.

But having said that, there are development tools available that will help you along the way but setting them up correctly will cost you some time at the beginning. Once you’ve spent that time and get it all into place, you’ll gain it back quickly.

Next, we’ll briefly cover the tools that I prefer to work with to create this automated workflow. There are plenty of good tools available, I’d be very happy to hear what tools you have found to solve the same, or other, challenges.

 

The tools

Git for Source code control

Git has quickly become the source control and versioning system of choice for many people. The WordPress development team still relies on Subversion but they are also making all of WordPress core as well as all plugins in the official repository available at Github as well.

Unit testing

To maintain code quality we need to use testing and since WordPress is a PHP project, the natural unit testing tool is PHPUnit by Sebastian Bergmann. There are plenty of good tutorials that will help you get started with PHPUnit and WordPress, one of my favorite guides is written by Pippin Williamson.

Vagrant as development eenvironment

Vagrant is a piece of software that will help you automate the creation of Virtual Machines right on your development computer. There are many benefits of running your WordPress project inside a Vagrant machine, the most obvious ones are that (1) you can install more or less the same software that you will use in production same version of Apache or nginx, same php version, same mysql version etc. And (2) you can make changes to the development environment without affecting the rest of your computer or any other projects. And (3) it’s super easy to make sure that all developers working on the same project actually has the exact same environment. No more “this works on my machine” conversations.

Grunt and wp-cli for automation

Wp-cli is a command line tool for automating installation and configuration of WordPress. It can be used to install a brand new WordPress site as well as to add or remove plugins, update individual settings such as “blogname” etc. We can use it to make sure that our WordPress installs are setup exactly the same in all of our environments (development, staging and production). Using wp-cli can be made even better when we add Grunt. Grunt is a JavaScript based command line tool that makes it easier to automate common tasks, like running a couple of wp-cli commands for instance. Grunt and wp-cli makes it possible to automate pretty much everything when it comes to WordPress installations.

WP-CFM

WP-CFM stands for WordPress configuration management. It’s a tool that helps us store a selection of WordPress settings from the database to a file that we keep in git. WP-CFM was built with wp-cli in mind, so by combining them we get a method of managing WordPress settings in the source code control system so that they are easily moved between development, staging and production. There are a few caveats, but there are luckily some workarounds for those.

Rocketeer for deployment

There are a few open source deployment systems available. The Ruby system Capistrano might be the most well known right now. For PHP developers there is a system called Rocketeer that does much of the same things but where you can reuse some of your PHP classes (and skills).

So, will WordPress and DevOps get along?

There are some distinct challenges when it comes to automating WordPress web development. In the tools list above I’ve outlined the tools I think we need to create a fully automated deployment process that enables us to move our project from development to other environments.

However, there are a few things that are not covered by any of these tools and it’s the primary reason that WordPress and DevOps sometimes can’t get along at all. It’s the content.

WordPress makes no distinction between content and content. For instance, your particular menu structure is store as a combination of taxonomies and posts. That’s right. A menu item is a type of post. And the start page of your WordPress site is a post. But the blog posts that are written by the site editors are also posts (naturally), and any images that are uploaded on the live site are also posts.

Our challenge is that when we deploy our WordPress site from development to production is that some content (menu and start page for example) are kind of part of the core web site you’ve created and you want the deployment process to transfer (and update) it on the live site. But other content is just content and if the deploy process overwrites normal posts we have a catastrophe on our hands.

WordPress has a hard time seeing the difference and that’s going to be the primary challenge when we want WordPress and DevOps to play along nicely.

 

Nitty gritty

Every item in the tool list, how to use them and how they fit into our process is a large enough topic for a 2-4 blog posts each. I’m not covering them in detail in this post. But as it happens, this post is only the first in a series of blog posts on these topics.

The next post will cover how to set up a good development environment using Vagrant and Git and after that we’ll look into automation with Grunt and wp-cli.

So stay tuned to this blog.

WordPress DevOps – The book

I’ve written an ebook on this subject. Released in September this year on Leanpub.com. Expect a 100+ tightly written pages where we walk through the creation of the skeleton of a WordPress based Saas application, connected to Stripe and Paypal with a working deployment process that takes content into account. Just add your billion dollar idea. Jump on over to Leanpub to get your copy.

WordPress DevOps - Strategies for developing and deploying with WordPress
WordPress DevOps – Strategies for developing and deploying with WordPress

 

 

 

 

 

 

 

[wysija_form id=”3″]

eBook on WordPress development and deployment

Advanced WordPress development

Last weeks I’ve been busy finishing up an eBook with the kind of straight forward title: WordPress DevOps – Strategies for developing and deploying with WordPress It’s a 100 page guide covering how You can get WordPress to work a little bit better in a proper development process, covering automation, testing and deployment.

If you’re interested, click here or on the book cover above to head on over to Leanpub and sign up for it. You’ll get an email as soon as it’s available for download. And yes, it will be available in pdf, epub and mobi formats. When you do sign up, please share your email address with me, I’d love to be able to stay in touch with you.