Articles, Tutorials

Ansible and WordPress: roles and playbooks

Since writing the article on why you should use Ansible for managing your WordPress deploys on VPS servers, I’ve added some basic configurations to my GitHub repo about this topic. In this article, we’ll be discussing how the standard Ansible project folder structure looks like and I’ll show you how to set up simple roles for PHP and WP-CLI installation on your VPS server.

Ansible project folder structure

Typical Ansible project folder structure contains these directories/files:


hosts — Ansible Inventory

This file consists of URLs of your VPS servers and custom groups which encompass those servers in logical ways.

Sample hosts file:


If I run ansible-playbook command with this hosts file, it will run all tasks specified in a playbook on each of those servers. The group [webservers] is used to limit which servers the tasks are executed on. More about Ansible Inventory on the official docs.

group_vars/ folder

group_vars is a folder containing variables for Ansible roles organized by groups. Taking the example hosts file with the group [webservers], the folder would have one file, named webservers in it. The contents of the webservers file are written in the YAML language.

Sample group_vars file (webservers):

# role: common
remote_deploy_user: deploy
remote_deploy_group: deploy
remote_deploy_home: /home/deploy

# role: wordpress-install
remote_www_dir: "{{ remote_deploy_home}}/projects"
remote_wordpress_dir: "{{ remote_www_dir }}/wordpress"
wordpress_db_name: wordpress
wordpress_db_user: deploy
wordpress_db_user_pass: deploypass
wordpress_db_prefix: wp_
wordpress_site_title: Test Site
wordpress_admin_user: admin
wordpress_admin_user_pass: adminpass

As you can see, data is actually stored as key-value pairs inside the file.

roles/ folder

The roles folder contains sub folders defining Ansible playbook roles. A role is a collection of tasks which will be executed on the VPS servers defined in the hosts file.

Let’s say that we have a “common” role with tasks that we want to be run in all our playbooks.


A role folder contains another folder called tasks which is composed of YAML files with our tasks for the role.

A sample tasks YAML file:

# roles/common/tasks/main.yml

- name: Update Apt
  apt: update_cache=yes

Here we define our first task called “Update Apt”. The apt module manages apt packages on Debian/Ubuntu systems. apt: update_cache=yes means that the apt cache will be updated, the same as running sudo apt-get update command on your VPS server manually.

Roles for PHP and WP-CLI

If we want to work with WordPress sites on our VPS servers, having PHP and WP-CLI installed on them is required. As WP-CLI is a PHP script, we need to have PHP installed first.

PHP role

Inside your roles/ folder create a new one called “php”. Inside the “php” folder, create yet another new one called “tasks”. Finally, add a new YAML file called main.yml to the “tasks” folder with following content:


- name: Add PHP v5.6 apt repository
    repo: 'ppa:ondrej/php5-5.6'

- name: Install PHP v5.6 for WP-CLI support
  apt: name={{ item }}
  - php5
  - php5-common
  - php5-mysqlnd
  - php5-mcrypt
  - php5-curl
  - php5-cli
  - php-pear

Let’s explain what’s going on here.

- name: Add PHP v5.6 apt repository
    repo: 'ppa:ondrej/php5-5.6'

This taks uses the apt_repository module to add a new PHP 5.6 PPA repository to our system’s sources list.

The next task — Install PHP v5.6 for WP-CLI support — uses the apt module to download and install PHP 5.6 and related libraries to our Ubuntu system. The {{ <variable_name> }} works as string interpolation for the following with_items: loop. On each loop, the variable item gets the value of looped item (e.g. “php5” or “php-common”, etc) so the apt command installs all the listed items.

The equivalent to this would be to execute:

apt-get install php5 php5-common php5-mysqlnd ...

on your Ubuntu VPS server manually.

WP-CLI role

After installing PHP with required and optional libraries, we can finally download and set up WP-CLI. We’ll follow the instructions on their official page but write them in the Ansible tasks language. Analogous to the PHP role described above, we create a file called main.yml in the roles/wp-cli/tasks/ folder with the content:


- name: Download WP-CLI
  shell: curl -O

- name: Make WP-CLI executable
    path: /root/wp-cli.phar
    mode: u=rwx,g=rx,o=rx

- name: Move WP-CLI to /usr/local/bin/wp
  command: mv /root/wp-cli.phar /usr/local/bin/wp

The shell module executes a shell command through a shell (/bin/sh) on the VPS server. It uses curl to download the wp-cli.phar file.

The file module manages attributes of files, as well as their modes and other cool stuff. We just need to make the file executable so we can run it from the command line later on.

The command module behaves similarly as the shell module except it doesn’t run through the shell, so variables like $HOME will not work. We don’t need to use a shell here, so no problem. We just move the wp-cli.phar file into /usr/local/bin/ as wp. This way, WP-CLI can be invoked just by running the wp command from our VPS Ubuntu’s shell.

Putting it all together

After configuring the PHP and WP-CLI roles, we need to set up a simple Ansible playbook. Create a file called playbook.yml in the project directory with the content:


- name: Installs PHP and WP-CLI with some essential software

  hosts: webservers
  remote_user: root

    - common
    - php
    - wp-cli

As you can notice, it will be run only on the VPS servers included in the [webservers] group described in the hosts Inventory file at the beginning of the article. Tasks will be run as the root user. We want to execute tasks from the php, wp-cli and common roles. The common role wasn’t described in the article. It contains tasks to perform some basic tasks such as setting the locale, updating the apt cache and installing some essential software. You can inspect it in my GitHub repo.

The final project directory structure looks like this:


To run the playbook, type

ansible-playbook -i hosts playbook.yml

from the command line in the project directory.

Note: you need to have your SSH Keys properly configured and added on your VPS servers for Ansible to work.

What’s next?

In the upcoming article, I’ll walk you through configuring MariaDB, Nginx and PHP-FPM Ansible roles. Stay tuned!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s