Category: WordPress

  • Freescout on SpinupWp

    Freescout on SpinupWp

    Update May 16th 2021: I’ve added a section about how to make sure SSL certificates are renewed automatically.

    In this tutorial I will go through the steps of setting up the open source helpdesk software Freescout on a SpinupWP site. I’m using this setup in production on a 2GB DigitalOcean droplet that is also hosting a bunch of WordPress sites and it’s running just fine, no performance issues to report.

    A 2GB droplet will set you back $10 USD per month. Combined with a $12 USD per month SpinupWP account you could be running a very competent support system with unlimited users starting at $22 USD per month with very little ongoing maintenance. If you’re already paying for these services chances are that the additional monthly cost for running Freescout will be zero.

    It’s quite likely that you will also want to get at few of the Freescout premium modules but note that they are pay once perpetual licenses so even if you end up spending $100 USD on those, your monthly fee won’t rise.

    I’ll be using a test domain that I have laying around called wundercogs.com and the resulting Freescout installation will get the address https://support.wundercogs.com, some of the config file edits and screenshots below will reflect that.

    For full disclosure. I’m not affiliated with Freescout or DigitalOcean but I do work for Delicious Brains, the makers of SpinupWP. None of the links in this post is an affiliate link.

    Step 1 – prerequisites

    Before we get started there are a few things we need to get sorted.

    We’re going to use a terminal shell to log on to the server using ssh. For security reasons SpinupWP only allows ssh logins using SSH keys (as opposed to using a password). If you’re not comfortable starting and using a command line shell this tutorial isn’t for you.

    We need to have a domain name. In this guide I’ll be showing some screenshots from hover.com and their DNS editor. But most DNS editors work more or less the same and you should be able to figure out out to make the same changes on your preferred domain name provider.

    Next we need to have an account with DigitalOcean because we’re using them to host our Freescout site. If you prefer to use another cloud server provider that’s fine, SpinupWP has plenty of documentation on how to provision servers from other providers.

    We obviously also need a SpinupWP account because we’re going to use SpinupWP to do all the heavy lifting also known as server management.

    Once we have both the DigitalOcean and SpinupWP accounts set up we’ll be following the SpinupWP docs to provision our first server. Their documentation is more than adequate so I’ll trust you’ll do just fine following that.

    If you happen to already have a provisioned server in SpinupWP it’s OK to use that, Freescout is a fairly light weight application so it’s fine to host it toghether with other SpinupWP sites.

    Once the server is setup in SpinupWP you can navigate to the server dashboard to find the IP number, make a note of it because we need it in the next step.

    Step 2 – setting up a domain name

    We’re going to configure a domain name to point to our newly created server. This step is important to do first because if we get this part right we’ll be able to get an SSL certificate without any additional hassle.

    To do this we’ll jump over to the DNS editor of our domain name hosting provider. As I mentioned earlier I’m using hover.com for this and this is what the steps looks like with them:

    Click Add record to add a host name to the domain:

    Enter a host name. In this tutorial we want Freescout to be accessible on the address support.wundergcogs.com, so the host name we add is simply “support” and then we fill in the server IP address we got from step 1:

    We finish by clicking Add record and we are all set.

    Step 3 – Creating a site

    To create a site we need to go back to the SpinupWP console and navigate to the server dashboard. Once there we hit the aptly named +Add site button to launch the site creation wizard

    On the first step we’ll add our domain name and make sure the Enable HTTPS (SSL/TLS certificate) checkbox is checked and then click next

    We’ll be asked if we’re ready to point our domain name to the server and since we’ve already taken care of that we’ll just click next and then I’ve updated the DNS

    …and a few moments later we should get the confirmation:

    On the next screen we’ll be asked what to install, we’re going to say Don’t Install Any Files because we’ll add the Freescout stuff later:

    Freescout needs to have a MySQL database set up so we need to add this on the next screen. Because we selected not to install anything on the previous screen we need to manually select Create New:

    Please note that SpinupWP automatically generates a database password on this screen. Be sure to copy it because you will need this password later.

    On the next screen we set Linux user name for our application. This is the Linux user account that Freescout will use to write files etc and SpinupWP will suggest a name based on the domain name we selected earlier which we will just accept. SpinupWP also suggests that we use PHP 7.4 for this site which is a sensible choice since at the time of writing this, Freescout isn’t confirmed to work with PHP 8 (but that may change).

    But we do want to uncheck the Enable full page cache checkbox since full page caching isn’t going to be needed and could quite frankly be a bit annoying for Freescout:

    And that will take us to the last wizard step which is just to confirm that everything looks OK

    …and since it looks just fine we’ll scroll all the way down and hit Add Site

    SpinupWP will take a few minutes to set up the site and that’s that.

    Step 4 – Creating a sudo user

    For the next steps we need to create a sudo user in SpinupWP. This is the user we will use to login to the server and install Freescout.

    To do this, we go to the server dashboard and click Sudo users:

    Here we need to make up our own username, let’s go with freescout and make a note of the auto generated sudo password as we will need it later.

    Important. You need to Add SSH Key to the newly created user because SpinupWP will not allow you to login using just the password. GitHub has a great guide for finding out your computers existing SSH key or help you generate a new one if needed. Make sure to upload your SSH public key to SpinupWP before saving the new user.

    Step 5 – Installing Freescout

    Ok, time for some keyboard work. First we’ll log on to the server using our newly created sudo user from the command line shell on your desktop / laptop:

    ssh [email protected]

    Once we’re on the server, navigate to the site folder for our site:

    cd /sites/support.wundercogs.com/

    And grab a copy of Freescout. Note that we’re running this command as the user support which is is the Linux user we created in step 4. When we issue this command we will have to enter the sudo password that we also created in step 4 above.

    sudo -u support git clone https://github.com/freescout-helpdesk/freescout

    Setting up a cronjob

    Freescout runs a lot of internal jobs every minute and to make that work we need to set up a cronjob. We create a new files as root:

    sudo nano /etc/cron.d/support

    …and enter the following:

    * * * * * support	php /sites/support.wundercogs.com/freescout/artisan schedule:run >> /dev/null 2>&1

    Then type Ctrl+o to save and Ctrl+x to exit the editor.

    Fixing server location

    Next, since we’re installing custom software here the webserver configuration files that SpinupWP generated for us will need a little tweaking. We’ll edit the nginx config file for our site so that nginx goes looking for the Freescout files in the right place.

    sudo nano /etc/nginx/sites-available/support.wundercogs.com/support.wundercogs.com

    About 10-12 lines down there’s a line starting with root, we’re going to change that line so that it reads:

    root /sites/support.wundercogs.com/freescout/public/;

    Then type Ctrl+o to save and Ctrl+x to exit.

    Fixing static files

    Freescout does a little trickery to be able to serve inline images and attachments correctly and to make that work we need to add a few lines in another nginx config file:

    sudo nano /etc/nginx/sites-available/support.wundercogs.com/server/static-files.conf

    You will see a lot of blocks starting with a descriptive comment on one line and the the word location on the next. Each block separated with blank a line. We need to add a new block to handle attachments near the top of the file, before the block that handles images with the comment “Caches images….”:

    # Manually added for Freescout
    location ~* ^/storage/attachment/ {
            expires 1M;
            access_log off;
            try_files $uri $uri/ /index.php?$args;
    }
    
    # Caches images, icons, video, audio, HTC, etc.
    ...
    ...

    Then type Ctrl+o to save and Ctrl+x to exit.

    Making sure SSL certificate auto renews

    When SpinupWP first creates the site it also sets up an SSL certificate which is needed for HTTPS to work. SpinupWP also takes care of renewing the SSL certificate on a regular basis. When this happens, the update script creates a file on disk and then asks the Letsencrypt service to verify that that file exists.

    We’ve just modified the nginx config a bit so the place where nginx looks for file to server doesn’t match the place where the update script will put that file for Letsencrypt. We’ll fix this by creating a simple symlink:

    sudo -u support ln -s /sites/support.wundercogs.com/files/.well-known /sites/support.wundercogs.com/freescout/public/

    Install IMAP support

    In most cases Freescout will be setup to use the IMAP protocol to fetch incoming emails. For this we need the PHP imap module installed:

    sudo apt-get install -y php7.4-imap

    That should be all the editing we need to do via ssh, to make the changes active, we just reload nginx:

    sudo service nginx reload

    Step 6 – Run the web installer

    We’re going to take the easy route and do the rest of the installation using the Freescout web installer. The installer is located at https://support.wundercogs.com/install. Use your browser and navigate to the corresponding URL on your domain to get started:

    Requirements should be OK:

    Permissions should also be OK:

    Make sure to select Use HTTPS Protocol:

    On the database setup screen we enter the database credentials we generated in Step 4, we only need to fill in database name, username and password, the rest is pre-filled:

    Select language and time zone on the next page:

    …and as the last step we create the admin user:

    And as as through magic we should get a happy success message telling us that everything went fine:

    Note that we took care of setting uo the cron job in a previous step. We’re done.

    Step 7 – Login

    So now we have a fully working Freescout installation running on a DigitalOcean droplet. The rest of all setup needed is handled via the Freescout web interface and is well documented over at the Freescout GitHub pages, you probably want to get started with:

    Feedback?

    Was this tutorial helpful? Did you miss anything or have you spotted any errors? Let me know in the comments below.

  • WordPress management the right way

    WordPress management the right way

    I first wrote about Wp-bootstrap in a post a few weeks ago and now it’s time for an update.

    New version 0.2.2

    Version 0.2.2 that was released today is actually quite a release. In this version, Wp-bootstrap is now feature complete to the extent that everything I described in my book, WordPress DevOps is now possible to do using Wp-bootstrap. This means that a bunch of Grunt scripts that quite honestly grew to be fairly complex can be replaced with a well formed, easy to read json file instead. I can’t tell you how nice that feels.

    Quality ASSURANCE

    I’ve got a separate repository on Github with the test cases for Wp-bootstrap. For the 0.2.2 release I spent a lot of time making sure to get code coverage up to an acceptable level. The overall coverage is now at 83%, a number I’m quite happy with at the moment. The missing 17% are in a part of the package that I’m considering scrapping and it’s not presented in the documentation, so no one should stumble on the untested code by mistake.

    References

    The big thing in this release is reference management. When you import options into WordPress using Wp-bootstrap, you might sometimes include a value that is actually a reference to a post ID. The most obvious example is the WordPress option “page_on_front” that stores the page ID for the page that works as the front page of your site. If you are using Wp-bootstrap to import the front page itself, chances are that the ID of that front page will be different between your development and production installations. So if you import the “page_on_front” setting, the integer value in the database will almost certainly be wrong.

    Wp-bootstrap can overcome this problem by managing these references for you. Just tell Wp-bootstrap which settings that contains references to a page/post/term. If that item was included in the imported data, Wp-bootstrap will update the database accordingly. This is a very powerful feature and it works across both posts (pages, posts, attachments custom post types) and taxonomy terms (categories, tags etc).

    Intended use case

    There is an intended use case or workflow that I had in mind developing this package. A quick overview:

    On the development server (hint: use Vagrant):

    • Start a new project by requiring wp-bootstrap in composer.json
    • Run vendor/bin/wpboostrap wp-init-composer to get easier access to the wp-bootstrap commands
    • Create a localsettings.json and appsettings.json
    • Make sure you exclude localsettings.json from source code control
    • Initiate the development installation with commands composer wp-install and composer wp-setup
    • As settings are updated, use the WP-CFM interface in WordPress Admin to include the relevant settings into the application configuration
    • As plugins and themes are needed, add them to appsettings.json and rerun the wp-setup command to get them installed into your local environment
    • As posts and menus are added, include them in appsettings.json.
    • When it’s time to deploy to a staging or production environment, run composer wp-exportcommand to get all content serialized to disk. Add them to your Git repo

    On the staging or production server:

    • Create the local database
    • Check out the project from Git
    • Create up your localsettings.json file with the relevant passwords and paths.
    • Run composer update
    • Run vendor/bin/wpboostrap wp-init-composer to get easier access to the wp-bootstrap commands
    • Run composer wp-install, composer wp-setup and composer wp-import

    Once the target environment has been setup, new changes from the development environment can be pushed by checking out the new changes using Git and rerunning wp-setup and wp-import.

    Take it for a spin

    Now it’s over to you. If you’re interested in a more structured workflow around WordPress, give Wp-bootstrap a try and let me know what you think in the comments section. Or better, get in touch to let me know how you can contribute to Wp-bootstrap. I’m eager to hear from you.

  • Easy wp-cli automation with wp-bootstrap

    Easy wp-cli automation with wp-bootstrap

    I’ve created a PHP Composer package to provide an easier way to automate WordPress installations using wp-cli. If you are unfamiliar with wp-cli and composer. I suggest you read up on composer here, wp-cli here and the rationale of automation in my book or in my blog series on the subject.

    Another great resources for learning more about using WordPress, git and Composer together is to check out the roots.io post on the subject as well as their Bedrock project.

    What is wp-bootstrap

    Wp-bootstrap is a composer package that adds a bunch of commands to your environment that helps you set up WordPress and themes, plugins and settings in a consistent manner using configuration files rather than scripts or worse, point and click installations. Wp-bootstrap depends on two files that it expects to find in your project root folder:

    1. appsettings.json that contains settings, themes and plugins that your WordPress site needs to use. It also has a way to manage some of the content of your application. This file is meant to be a part of your application and managed in a source code control system.
    2. localsettings.json that contains settings that are specific to each environment. This includes database name, password, WordPress installation path and more. This file is meant to be unique to each environment that your site runs in (development, staging, production etc) and is not supposed to be managed by source code control.

    By combining these two files wp-bootstrap is able to setup a WordPress installation from scratch, let’s see how.

    INSTALLING wp-bootstrap

    [code]
    {
    "require": {
    "eriktorsner/wp-bootstrap": "0.2.*"
    }
    }
    [/code]

    [code]
    $ composer update
    $ vendor/bin/wpbootstrap wp-init-composer
    [/code]

    To include wp-bootstrap to your project, just add the above lines to your composer.json file. Or if you prefer, use this command:

    [code]
    $ composer require eriktorsner/wp-bootstrap
    $ vendor/bin/wpbootstrap wp-init-composer
    [/code]

    By running the command “vendor/bin/wpbootstrap wp-init-composer” to add the wp-bootstrap commands to composer so that you can call wp-bootstrap easier, this step is not strictly needed.

    LOCALSETTINGS.JSON

    In addition to installing wp-bootstrap, you also need to have a localsettings to tell wp-bootstrap where to find your database, some of the credentials and where to install WordPress (where the web server expects to serve the files from). Note that your’re not really supposed to install WordPress in the same folder as your configuration files. Here’s a sample localsettings.json file:

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

    I think it’s fairly self explanatory, but here it goes:

    • environment is typically one of the values “development”, “staging” or “production”. A description of the environment that this installation is
    • url The url for this installation
    • dbhost, dbname, dbuser and dbpass are the database credentials. Wp-bootstrap assumes that a database already exists and is accessible using those credentials
    • wpuser, wppass are the credentials for the default WordPress admin user.
    • wppath is the path where WordPress will be installed.

    APPSETTINGS.JSON

    The last thing you need to add is an application settings file. The very minimum file you need to provide is:

    [code]
    {
    "title": "TestingComposer approach";
    }
    [/code]

    Title is the only mandatory field in this file, but it’s far from the only one.

    Section: plugins:

    This section consists of two sub arrays “standard” and “local”. Each array contains plugin names that should be installed and activated on the target WordPress site.

    • standard Fetches plugins from the official WordPress repository. If a specific version is needed, specify the version using a colon and the version identifier i.e if-menu:0.2.1
    • local A list of plugins in your local project folder. Plugins are expected to be located in folder projectroot/wp-content/plugins/. Local plugins are symlinked into place in the wp-content folder of the WordPress installation specified by wppath in localsettings.json

    Section: themes

    Similar to the plugins section but for themes.

    • standard Fetches themes from the official WordPress repository. If a specific version is needed, specify the version using a colon and the version identifier i.e footheme:1.1
    • local A list of themes in your local project folder. The themes are expected to be located in folder projectroot/wp-content/themes/. Local themes are symlinked into place in the wp-content folder of the WordPress installation specified by wppath in localsettings.json
    • active A string specifying what theme to activate.

    Section: settings

    A list of settings that will be applied to the WordPress installation using the wp-cli command “option update %s”. Currently only supports simple scalar values (strings and integers)

    Using wp-bootstrap

    The easiest way to use wp-bootstrap is to simply call the binary file that is added to your vendor/bin subfolder. Using the sample files above, you could do this:

    [code]
    # Install WordPress
    $ vendor/bin/wpbootstrap wp-install

    # alternate:
    $ composer wp-install
    [/code]

    After running this command, you should have a fully working WordPress installation, accessible via the url specified in your localsettings.json file. The title of the site should match whatever you specified as the title attribute in the appsettings.json file.

    More Settings

    So far we’ve managed to reproduce what wp-cli can do in three separate commands, good but perhaps not that great. The real power of wp-bootstrap lies in extending appsettings.json with some more settings. Here’s a slightly more advanced example:

    [code]
    {
    "title": "TestingComposer approach",
    "plugins": {
    "standard": [
    "if-menu:0.21",
    "baw-login-logout-menu",
    "wp-cfm",
    "google-analyticator",
    "wpmandrill"
    ],
    "local": [
    "wordpressapp"
    ]
    },
    "themes": {
    "standard": [
    "agama"
    ],
    "active": "agama"
    },
    "settings": {
    "blogname": "New title 2",
    "blogdescription": "The next tagline"
    }
    }
    [/code]

    Using this file, we can customize the WordPress installation with a new command:

    [code]
    # Install plugins, themes etc.
    $ vendor/bin/wpbootstrap wp-setup

    # alternate
    $ composer wp-setup
    [/code]

    Let’s walk through this:

    • In the Plugins section, we specify a number of standard plugins that will be fetched, installed and activated from the WordPress plugin repository. The if-menu plugins will be installed with version 0.21, but the rest of that list will just be whatever version that is the latest in the repository
    • We also install and activate a local plugin that will be symlinked from [project root]/wp-content/plugins into the WordPress installation. This is so that we can include our own plugins developed specifically for this project.
    • The themes section works very similar, the theme agama is added to the installation from the WordPress theme repository and it’s also set as the active theme.
    • And finally, the settings “blogname” and “blogdescription” are overwritten with the values specified. These names corresponds to what the settings are called in the wp_options database table.

    There are more settings…

    If you’re curious enough to try this, I suggest you head on over to the github page for this project. It got some additional settings that you should read up on, especially if you’re keen to manage pages, menus and images in a similar fashion.

    I’m also very curious to hear what you think about this, don’t hesitate to let me know in the comments. You can also reach out to me on Twitter with comments or questions.

     

    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 configuration management

    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.

    [code firstline=”36″ title=”wp-setup task in Gruntfile” language=”js” highlight=”47-49″]

    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"’);

    })
    [/code]

    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:

    [code title=”wp-content/config/settings.json” language=”js”]
    {
    "blogdescription": "experimental tagline",
    "blogname": "New blog title",
    "posts_per_page": "20",
    ".label": "settings";
    }
    [/code]

    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:

    [code title=”Gruntfile.js” language=”js” firstline=”53″]

    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’);
    });

    [/code]

    • 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

    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

    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.

    [code firstline=”53″ title=”getLocalsettings” language=”js”]

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

    [/code]

    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

    [code title=”localsettings.json” language=”js”]

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

    [/code]

     

    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:

    [code title=”Grunt default task” language=”js”]

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

    [/code]

    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:

    [code language=”shell”]
    $ cd /vagrant
    $ grunt
    Running "default" task
    localsettings successfully read URL=www.gruntautomationforwp.localOK

    Done, without errors.
    [/code]

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

    [code title=”Gruntfile wp-install” firstline=”14″ language=”js”]
    /*
    * 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="[email protected]" –admin_password="’ + ls.wppass + ‘"’);
    } else {
    grunt.log.write(‘WordPress is already installed’).ok();
    }
    });
    [/code]

    • 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:

    [code language=”shell”]
    $ 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.
    [/code]

    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:

    [code title=”Gruntfile wp-install” firstline=”32″ language=”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);
    }
    })
    [/code]

    • 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:

    [code language=”shell”]
    $ 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.

    [/code]

    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:

    [code language=”shell”]
    $ cd /vagrant/www/wordpress-default/
    $ wp option list | grep ‘WordPress App’
    blogname WordPress App
    [/code]

    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”:

    [code language=”shell”]
    $ wp option list | grep ‘ust another WordPress site’
    blogdescription Just another WordPress site
    [/code]

    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:

    [code language=”shell”]
    shell.exec(wpcmd + ‘option update blogname "Another title"’);
    shell.exec(wpcmd + ‘option update blogdescription "experimental tagline");
    [/code]

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

    [code language=”shell”]
    $ 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.
    [/code]

    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

    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:

    [code]
    $ vagrant plugin install vagrant-hostsupdater
    [/code]

    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.

    [code language=”ruby”]
    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    hostname = ‘wpvagrant’
    ipnumber = ‘192.168.50.33’
    devdns = ‘www.wpvagrant.local’
    testdns = ‘test.wpvagrant.local’
    [/code]

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

    [code]
    $ vagrant up
    [/code]

    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:

    [code]
    $ 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:~$
    [/code]

    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

    [code]
    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
    [/code]

     

    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.

    [code]
    $ cp localsettings.json.template localsettings.json
    [/code]

    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.

    [code]
    $ npm install
    [/code]

    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:

    [code]
    $ grunt wp-install
    [/code]

    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

    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″]

  • WordPress file permissions

    WordPress file permissions

     

    In order for WordPress to be able to install a plugin and plugins or themes automatically there are a number of conditions that have to be met. If all those conditions aren’t met, one-click installations or upgrades won’t happen, instead, whenever you try to upgrade, WordPress will show you the FTP credentials input form. If you’re anything like me, you hate it.

    I sometimes run into this problem. My first instinct is to check the obvious file permissions. Will the web server have write access to all the important places. As long as we’re only talking about plugins and themes, important places means the wp-content folder. When I’m certain that the web server have write access, I typically try again and successfully upgrade my plugin.

    Every once in a while, installing or upgrading still won’t work even if I’m 100% certain that WordPress should be able to write everywhere it needs to. I end up searching for a solution for about 10 minutes, give up and resort to manually uploading plugins via ssh and get on with my life. Today I decided to find out the root cause of this problem and solve it. Writing this blog post about it servers as much as a ‘note to self’ as assistance to anyone else that trouble shoots this without finding a solution.

    The rules

    So, the rules for WordPress to be able to install and upgrade plugins and themes:

    1. The web server needs to have write access to the wp-content folder. For example on a Debian based system (i.e Ubuntu), this will be user ‘www-data’, on RedHat/Fedora, it’s typically user ‘httpd’ (plese correct me here if I’m wrong). WordPress will test this by writing a temporary file to wp-content and then remove it. There are plenty of blog posts, howtos and forum posts about this. They usually points back to this article: http://codex.wordpress.org/Changing_File_Permissions
    2. The files in wp-admin needs to be owned by the web server user. WordPress will test this by using PHP function getmyuid() to check if the owner of the currently running PHP script is that same as the owner of the newly created temporary file. If it’s not the same, WordPress will select another method of installation or upgrade.

    Rule #2 is what typically gets me. Whenever I move an existing WordPress installation to a new home, I’m sometimes (obviously) not careful with setting file permissions and file ownership and end up in this situation. Rule #1 is extremely intuitive, checking for write permission is close to second nature. But Rule #2,  checking file ownership in wp-admin… well, I’d even say it’s slightly unintuitive. If anything is worth protecting it should be the admin area, and being more restrictive with file ownership and permissions under wp-admin would even kind of make sense.

    Anyway. Comments, questions or other feedback. Please post a comment below.

     

    [wysija_form id=”3″]