davekiss.com

Develop WordPress Sites Like a Goddamn Champion

Last updated: May 30th, 2016

WordPress has always been the orange cucumber in the room. Everyone knows about it. Some folks hate it. Men want to be it. And yet, the percentage of the web that it powers continues to climb every year.

Maybe it's due to its user-friendly admin panel. Or, perhaps it's because anyone with a copy of Dreamweaver CS2 can FTP into a LAMP stack and make changes on the fly.

Regardless, it's worth considering that the business benefits of developing for WordPress might arguably outweigh the drawbacks of its wonky codebase, questionable practices, and the outdated toolchain used to manage a vast majority of installs.

So, what do we do? How can you develop for WordPress in the 21st century without feeling like a total hack?

Roots to the Rescue

The folks over on the Roots development team have long recognized the quirks with WordPress and have assembled a team of smart brains to do something about it. Their latest project, called Trellis, aims to replace the antiquated approach to creating and managing WordPress environments.

A second Roots project, called Bedrock, provides a WordPress boilerplate with modern development tools, easier configuration, and an improved folder structure. When used in tandem with Trellis, you'll have all the professional tools in place to take the WordPress world by storm.

This article will show you exactly how to use Bedrock and Trellis together to create, develop for, provision, and manage servers in parity, along with deploying your code to each of those environments, making you a total WordPress badass.

This might take a little while, but you'll thank me once it's all set up.

Requirements

Let's get started

First things first: I'm developing on a Mac Mini, using OS X Yosemite. While Bedrock and Trellis can be used on most any operating system and machine, this article will be detailing installation and usage instructions for folks in a similar environment.

In order to get going with using this stack, there are a few other programs that you need to install first. We're going to use Terminal to install these dependencies.

Terminal offers a command-line interface (CLI), which is a means of interacting with your system where you'll issue commands in the form of successive lines of text. That's right baby, no menus or shiny icons here. You're a real hacker now.

Terminal is located in the Applications/Utilities folder. Alternatively, you can use Spotlight to search for and open it up.

You'll know you're ready to go when that big, scary, empty black box pops up. For the remainder of this tutorial, we'll call this box the CLI.


Installing Dependencies

A quick note: the sections below using a convention of highlighting text to show what you must enter into your CLI. If you see text that looks like this, it means that you should literally type like this into your CLI and press enter.

The following programs are required to be installed on your system before using Bedrock and Trellis:

  • Homebrew
  • Git
  • Ansible 2.0.2
  • Composer
  • VirtualBox
  • Vagrant

If you know you have these programs installed already, you can skip down to the Configuring Trellis section below. If not, read on.

Homebrew

The first program that we'll install is called Homebrew, a package manager for OS X that allows you to install and configure other programs on your Mac. I know, meta, right?

To install Homebrew, copy and paste the following command into your CLI:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

During the installation process, you may be prompted to press Enter or type in your Mac password. Don't be shy! Just follow the instructions until Homebrew finishes doing its thing.

Once it's done, you can type the following command into your CLI to ensure everything is set up properly:

brew doctor

Git, Ansible and Composer

Now that we're ready to brew, let's use the brew command to install three of our remaining dependencies: Git, Ansible, and Composer. Type the following command into your CLI to install those packages:

brew install git ansible composer

Homebrew will barf out a ton of stats and information, and once it has finished without errors, you're ready to move on.

VirtualBox

Next, we'll want to install VirtualBox, an open source virtualization program that we'll use to create imaginary servers on our development machine. You can download the proper version of VirtualBox from the VirtualBox downloads page.

Once VirtualBox has finished downloading, make sure to double-click the DMG file that was saved to your computer and follow the on-screen prompts to complete the installation.

Vagrant

Phew! Almost done. The last thing we want to install is Vagrant, a program which will allow us to create and configure lightweight, reproducible, and portable development environments. It is an amazing tool for managing virtual machines via a simple-to-use command line interface.

You can download the proper version of Vagrant from the Vagrant downloads page. Once Vagrant has finished downloading, make sure to double-click the DMG file that was saved to your computer and follow the on-screen prompts to complete the installation.

BOOM! Time to move on.


Installing Trellis

Wait, we're how many words into this article, and we haven't even touched Trellis yet? I know. Time to change that.

For the purpose of this article, we're going to create and run our new WordPress site out of the current user's sites directory (if it doesn't exist, we'll create it.)

If you already have a directory that you'd like to work out of, make sure to replace any occurrences of ~/sites/ in the remainder of this article with the directory of your choice.

Let's first create the folder that we're going to build our WordPress site in. Enter the following commands in your CLI, one at a time, replacing example.com with the actual name of the project that you're working on.

mkdir -p ~/sites/example.com  
cd ~/sites/example.com  

Now that we've told our CLI to work out of that new directory, let's download and install Trellis into it by cloning the public Git repository. Use this command to do so:

git clone git@github.com:roots/trellis.git ansible

You should see a new folder in your example.com directory called ansible which contains the core install of your Trellis repo. Sweet!

Now, let's fetch the external Ansible roles/packages that Trellis will use when provisioning your virtual machines and servers. You can do so with the following command in your CLI:

cd ~/sites/example.com/ansible && ansible-galaxy install -r requirements.yml


Installing Bedrock

"So, we've installed Trellis and a hundred other programs, but what about our friend Bedrock? Also, are we almost done installing things? I only have 200MB left on my hard drive :(

Yes, I promise you the installation process is coming to an end. But, not before we run the following command to download the Bedrock repo and place it in our example.com folder:

cd ~/sites/example.com && git clone git@github.com:roots/bedrock.git site

Heck yeah, son! You've gotta be a Git pro by now.

A Word about Composer

The cool thing about Bedrock is that it enables support for managing your WordPress themes, plugins, and core install via Composer, which is yet another package manager made specifically for PHP packages.

So what does that mean for you? Well, instead of updating WordPress core from the admin panel, or letting your plugins run amuck with updates on the admin plugins page, you can define your site requirements and dependencies entirely within a single composer.json file.

Ultimately, It will make development more reliable, help with team collaboration, and help you maintain a better Git repository. Trust me, this rules.

Let's grab the WordPress core now with the following command:

cd ~/sites/example.com/site && composer install


Configure WordPress

Okay, so we have WordPress installed. Let's get our connection settings configured and actually get that sucker running, whaddya say?

Open the file located at ansible/group_vars/development/wordpress_sites.yml in your preferred text editor. I'm using Sublime Text which allows me to run the following command to open the correct file automatically:

subl ~/sites/example.com/ansible/group_vars/development/wordpress_sites.yml

The contents of this file will define our WordPress development environment settings, including the url of your site, database connection details, admin info, and other environment variables.

For now, we only care about setting the connection details to our future development site and database. Look for the below settings, and change them so that you replace any instance of example with your actual site name.

wordpress_sites:  
  example.com:
    site_hosts:
      - example.dev
    local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
    site_title: Example Site
    admin_email: admin@example.dev

    # You can set ssl enabled: false if you don't want to require https
    # Otherwise, Trellis will generate a self-signed certificate for you.
    ssl:
      enabled: true
    multisite:
      enabled: false
    cache:
      enabled: false

We'll also want to add our WordPress admin password and MySQL database password to our vault file, which is specifically meant to hold sensitive data. Open the file located at ansible/group_vars/development/vault.yml and make sure to configure the following settings:

# Variables to accompany `group_vars/development/wordpress_sites.yml`
vault_wordpress_sites:  
  example.com:
    admin_password: example_wordpress_admin_password
    env:
      db_password: example_dbpassword

Make sure to save once you've made the proper changes.

Alright, I'm sick of all this code configuration BS, and I'm sure you are too. It's time to provision our virtual development machine. Let's run the following command to get everything up and running:

cd ~/sites/example.com/ansible && vagrant up

At this point, your computer will start doing things that Alan Turing could only dream of. Trellis is gonna use Vagrant and Ansible to go through all of its default settings and create an awesome virtual web server in an isolated container on your machine, using a modern LEMP stack that can be further configured, if desired.

Near the beginning of this process, you'll be prompted to enter your system password which will give Vagrant permission to write to your system's /etc/hosts file. Vagrant will create an entry that allows your browser to route incoming requests for your site's URL to the virtual machine that is being configured.

Go get a beer, and once this process has finished without errors, type your site URL in your favorite browser.

Feeling like a goddamn champion yet?


Adding WordPress plugins

If you've made it this far, it's now time to start seeing the fruit of all your hard labor. Let's go over how to install WordPress plugins on our newly configured site.

I'm sure it has happened to everyone: you or a client notice a update is available for one of your WordPress plugins in the admin dashboard. Sweet! You go to get the latest version, and soon after were wishing you never clicked "Update" – bombarded by errors, or, worse, a blank screen with nothing at all.

Installing untrusted and untested code on your website is a terrible practice and habit. Bedrock will prevent the use of updating plugins from the WordPress dashboard, and instead, moves this process to your development environment using Composer.

This allows you to check your plugin updates into your version control system and easily find the issues and perform a rollback to working code if an update goes sour.

To add a plugin, open the file located at site/composer.json in your preferred text editor.

subl ~/sites/example.com/site/composer.json

In this file, you'll see a block of code that resembles the following:

  "require": {
    "php": ">=5.5",
    "composer/installers": "~1.0.12",
    "vlucas/phpdotenv": "^2.0.1",
    "johnpbloch/wordpress": "4.5.2",
    "oscarotero/env": "^1.0",
    "roots/wp-password-bcrypt": "1.0.0"
  },

This code is defining the required packages that your WordPress site depends upon. These dependencies will all be installed/updated on your server whenever you or ansible runs the composer install and composer update commands in your CLI.

Every WordPress plugin on wordpress.org is mirrored by a nifty little service called wpackagist. We'll use this service as the host from which to install our WordPress plugins.

Let's add a line to this block to install the Vimeography video gallery plugin:

  "require": {
    "php": ">=5.5",
    "composer/installers": "~1.0.12",
    "vlucas/phpdotenv": "^2.0.1",
    "johnpbloch/wordpress": "4.5.2",
    "oscarotero/env": "^1.0",
    "roots/wp-password-bcrypt": "1.0.0"
    "wpackagist-plugin/vimeography": "1.3.2"
  },

As you can see, we told Composer to look for a wpackagist-plugin called vimeography and to use version 1.3.2 - if we always wanted to use the latest version, we could instead use dev-trunk in place of the version number, but I like to be explicit about which versions I use.

Now, back in your CLI, we'll tell composer to refresh all of our required packages by running this command:

composer install && composer update

Head back over to your WordPress dashboard and visit the plugins page to revel in your success.


Time to Go Live

Up until now, we've been working on our website locally, meaning that it isn't actually published anywhere that is publicly accessible. Let's change that and get you running on a real live webserver.

Digital Ocean

For the purposes of this tutorial, we are going to set up the WordPress site on a VPS over at Digital Ocean. It's a great alternative to traditional shared hosting because it is built on super fast solid state drives and it is very friendly on the wallet.

If you're new to Digital Ocean, you can sign up through this link and receive a free $10 credit, good for two free months of WordPress hosting.

After you've created and logged in to your Digital Ocean account, it's time to start setting up the server.


Create a New Droplet

DigitalOcean calls its virtual private servers droplets; each droplet that you spin up is a new VPS for your personal use. The setup is very easy – let's create one now.

Note: you'll want to have an SSH key ready to access your new droplet. An SSH key is basically a password that tells your droplet to allow incoming connections from your computer. You can learn how to make one from the GitHub help page

Start by clicking the green Create Droplet button at the top of the page.

  • Choose an Image: Click on the Distributions tab, and choose Ubuntu on 14.04 x64 – it should be selected by default.
  • Choose a Size: $5/month
  • Choose a Datacenter Region: New York 3
  • Select additional options: None
  • Add your SSH Keys: (Optional) Paste your SSH key here
  • Choose a Hostname: My Example Site

Once you're selected the options above, click the big green Create Droplet button at the bottom of the page.

After about a minute, your new droplet will be created and ready to rock. It will also be assigned an IP address, which you can find on the droplet details page. Copy this IP address down and save it somewhere safe.


Domain Forwarding

Now that you have a droplet ready to go, you'll need to configure your domain name so that it sends you over to your new server when you visit the site in your browser.

To do this, you'll need to Add a Domain to your DigitalOcean account by clicking on the Networking menu item.

If you don't have a domain name yet, I'd recommend NameCheap as a quick and easy way to purchase a new domain name and get it set up quickly.

There are 2 values you'll need to enter for your new domain:

  • Domain: example.com (replace with your actual domain name)
  • Droplet or Custom IP: Select the Droplet that you just created

Click Create Record and take a swig of your beer (or water.)


Pushing to GitHub

If you're not familiar with the concept of version control, now is a great time to get started. You'll need to push your code up to your GitHub account so that Trellis can copy it over to your live droplet. GitHub also makes it easy for multiple developers to work on the same project at once.

Head on over to GitHub and create a new repository, making sure to uncheck the box next to "Initialize this repository with a README."

Now, let's add your WordPress site to GitHub using the CLI by entering the following commands, one by one:

cd ~/sites/example.com/site  
git init  
git add .  
git commit -m "First commit"

# replace the line below with your actual remote repository URL
git remote add origin git@github.com:example/example.com.git  
git push origin master  

If all goes well, you should see a message similar to the one below in your CLI:

Counting objects: 3, done.  
Delta compression using up to 4 threads.  
Compressing objects: 100% (3/3), done.  
Writing objects: 100% (3/3), 315 bytes | 0 bytes/s, done.  
Total 3 (delta 2), reused 0 (delta 0)  
To git@github.com:example/example.com.git  
   b17da4e..96a91c1  master -> master

Onward!


Configuring your Live Settings

Remember your Droplet IP Address from before? It's time to put it to use. Copy that IP address, and then, back on your computer, open up the file located at ansible/hosts/production in your preferred text editor. In this file is where we'll tell ansible to deploy all of our WordPress code.

# Add each host to the [production] group and to a "type" group such as [web] or [db].
# List each machine only once per [group], even if it will host multiple sites.

[production]
# Swap the line below with your *actual* droplet IP address
your.droplet.ip.address

[web]
# Swap the line below with your *actual* droplet IP address
your.droplet.ip.address  

Now we'll configure our live site settings, just like we did with our development site settings earlier in this article. Open ansible/group_vars/production/wordpress_sites.yml in your preferred text editor.

subl ~/sites/example.com/ansible/group_vars/production/wordpress_sites.yml

We're going to go through the same process with this file as we did with the group_vars/development/wordpress_sites.yml version, only, we'll be a little more specific and secure about the settings we're using here.

# Documentation: https://github.com/roots/trellis#wordpress-sites
wordpress_sites:

  example.com:
    site_hosts:
      - example.com
    # enter the path to your website's Git repo
    repo: git@github.com:example/example.com.git
    ...
    ssl:
      enabled: true
      provider: letsencrypt
    cache:
      enabled: true
      duration: 30s

We'll also want to set more secure passwords and secret keys, which can be done by editing the vault file located at ansible/group_vars/production/vault.yml:

# set vault_mysql_root_password to something more secure
# Documentation: https://roots.io/trellis/docs/vault/
vault_mysql_root_password: * GENERATE A SECURE, RANDOM PASSWORD HERE *

# Variables to accompany `group_vars/production/wordpress_sites.yml`
vault_wordpress_sites:  
  example.com:
    env:
      db_password: * GENERATE A SECURE, RANDOM PASSWORD HERE *
      # Generate your keys here: https://api.wordpress.org/secret-key/1.1/salt/
      # These CANNOT contain the characters "{%" in succession
      auth_key: "generateme"
      secure_auth_key: "generateme"
      logged_in_key: "generateme"
      nonce_key: "generateme"
      auth_salt: "generateme"
      secure_auth_salt: "generateme"
      logged_in_salt: "generateme"
      nonce_salt: "generateme"

      # Any other custom environment variables can be defined below
      my_super_secret_api_key: "dont_tell_anyone"

Connecting your GitHub Account

We're nearing the end. Can you taste the victory?

We need to tell ansible about your GitHub account so that all of your code in your GitHub repo can be successfully copied over to your live server. Simple enough – open the file located at ansible/group_vars/all/users.yml in your preferred text editor.

subl ~/sites/example.com/ansible/group_vars/all/users.yml

This file tells Trellis which users should be authorized to perform certain actions, such as provisioning the live server, or deploying WordPress sites.

We'll need to modify this file so that Trellis knows which GitHub usernames are allowed to communicate with your live server.

Change the contents of this file by modifying all of the lines that look like this:

# - https://github.com/username.keys

Uncomment the line (remove the # symbol) and replace the username in username.keys with your actual GitHub username (go figure).

Those lines should now look something like this:

- https://github.com/davekiss.keys


Tasty Provisions

Our hard work is done. Now it's time to let the robot army take over and set up a professional live site environment with a single command. Enter the following command in your CLI to set up your droplet with all of the required software.

cd ~/sites/example.com/ansible && ansible-playbook server.yml -e env=production

Trellis and ansible will provide you with some feedback throughout this process so that you can see exactly what is going on. You can either watch and learn what it is doing, or, go have another beer. No really, it's fine. I'll drive.

Once completed successfully, your new droplet will be ready for your incoming WordPress site.


Deployment

As you proceed to make some awesome website code stuff, you'll eventually want to push it out to your live droplet so that you can share your work with the world.

The first thing you'll want to do is make sure that all of your latest and greatest code is up on your GitHub repository. You can do that by committing to your repository and pushing it to GitHub by issuing the same command that we did before:

cd ~/sites/example.com/site && git push origin master

If everything looks good, we can launch your code over on your droplet by using this command in your CLI:
cd ~/sites/example.com/ansible && ./deploy.sh production example.com

Visit your site and begin to cry tears of joy.


Success!

YES! BEER! You have a professional development environment all set up, and you're paying $5 a month. Your new development process should now look like this:

  • write your code/tests and make sure everything works on example.dev
  • commit your code to your repository and push it up to GitHub
  • when ready, send your code to your live server with ./deploy.sh production example.com
  • rinse and repeat

Questions or comments? Use the comments below or hit me up on Twitter, @davekiss

Author image
About Dave Kiss
I'm a full-stack developer that started my own business and grew it to a sustainable level over the past few years. I'm happy to share my techniques, results, failures, successes, and ideas with you.