Automated WordPress installation with Ansible

In the second article of the Ansible and WordPress series, we discussed the basic Ansible project structure and setting up WP-CLI and PHP. Today, I’ll walk you through creating a new database, adding a new user with correct permissions to this database, downloading WordPress with WP-CLI and configuring it properly to use our newly created database. You can find complete source code of these series at my wordpress-ansible GitHub repo.

You need to have MySQL/MariaDB as well as PHP and WP-CLI installed on your VPS server before being able to successfully execute the following tasks.

Create a new Ansible role

We need to create a new Ansible role. Let’s call it wordpress-install. Add two new folders inside the wordpress-install role folder — tasks and vars. Variables such as WordPress database user, his password, home URL and others will go into the vars/main.yml file, while the tasks to install WordPress will go into tasks/main.yml.

Tasks for WordPress configuration

I’ll show you all the tasks first and explain them later.

- name: Create WordPress database
  mysql_db: name="{{ wordpress_db_name }}"
            login_password="{{ mysql_root_password }}"

- name: Create WordPress DB user and grant permissions to WordPress DB
  mysql_user: name="{{ wordpress_db_user }}"
              password="{{ wordpress_db_user_pass }}"
              priv="{{ wordpress_db_name }}.*:ALL"
              login_password="{{ mysql_root_password }}"

- name: Is WordPress downloaded?
  stat: path="{{ remote_wordpress_dir }}/index.php"
  register: wordpress_is_downloaded

- name: Create WordPress directory
  file: path="{{ remote_wordpress_dir }}"
        owner="{{ remote_deploy_user }}"
        group="{{ remote_deploy_group }}"
  when: wordpress_is_downloaded == False

- name: Download WordPress
  command: wp core download
      chdir: "{{ remote_wordpress_dir }}/"
  remote_user: "{{ remote_deploy_user }}"
  when: wordpress_is_downloaded == False

- name: Configure WordPress
  command: wp core config
           --path="{{ remote_wordpress_dir }}"
           --dbname="{{ wordpress_db_name }}"
           --dbuser="{{ wordpress_db_user }}"
           --dbpass="{{ wordpress_db_user_pass }}"
           --dbprefix="{{ wordpress_db_prefix }}"
  remote_user: "{{ remote_deploy_user }}"
  when: wordpress_is_downloaded == False

- name: Is WordPress installed?
  command: wp core is-installed
    chdir: "{{ remote_wordpress_dir }}/"
  register: wordpress_is_installed
  ignore_errors: True
  remote_user: "{{ remote_deploy_user }}"

- name: Install WordPress tables
  command: wp core install
            --url="{{ wordpress_home_url }}"
            --title="{{ wordpress_site_title }}"
            --admin_user="{{ wordpress_admin_user }}"
            --admin_password="{{ wordpress_admin_user_pass }}"
            --admin_email="{{ wordpress_admin_email }}"
      chdir: "{{ remote_wordpress_dir }}/"
  when: wordpress_is_installed|failed
  remote_user: "{{ remote_deploy_user }}"

Create WordPress database

The first task is to create a new database, which will be used to store WordPress tables. Ansible comes with the mysql_db module — exactly what we need. The first parameter name= accepts the name of the WordPress database. Let’s have it more dynamic and use a variable instead of static string. Define this variable in the vars/main.yml file. For example

wordpress_db_name: wordpress

Parameters login_user= and login_password= are the credentials for authenticating with your MySQL/MariaDB database software. Define the mysql_root_password in the vars/main.yml file as well.

Create WordPress DB user and grant permissions to WordPress DB

In the second task, the mysql_user module is utilized. We give the user a name and password and then granting him all privileges on our newly created database on the priv="{{ wordpress_db_name }}.*:ALL" line. The state=present means that the user is ought to be created. If it was set to state=absent, Ansible would remove the user from the database instead.

Is WordPress downloaded?

WP-CLI doesn’t check whether WordPress Core files are already downloaded or not. When running the Ansible tasks multiple times, the task to download WordPress produces an error. Therefore, checking if WordPress has already been downloaded or not and running the download task only if it hasn’t been is a good idea. We use a handy feature named registered variables here. Together with the stat module, we can detect if WordPress is downloaded and remember it in a variable that can be used in the following tasks.

Create WordPress directory

A simple task which creates a new directory that will hold the WordPress core files. Notice the when clause at the end of the task. The task will be executed only if the Jinja2 expression in the when clause evaluates to True. Exactly what we need.

Variables {{ remote_wordpress_dir }}, {{ remote_deploy_user }} and {{ remote_deploy_group }} must be defined in the vars/main.yml file. There is an example of this file at the bottom of the article.

Download WordPress

In this task, the wp WP-CLI command line application is invoked with parameters to download the WordPress core. What’s interesting about this task is that the command module changes directory to our WordPress project directory before calling the wp program with the help of args: parameter. Ansible also runs the command module with a non-root user defined in the remote_deploy_user variable. Note: you need to have this user created before Ansible can use it.

Configure WordPress

WP-CLI — being an extremely awesome tool — comes with a command to automatically configure WordPress installation for us. We just need to supply it with a few parameters and job’s done!

Is WordPress installed?

This task checks whether WordPress database tables has already been inserted into our database. Trying to insert them with WP-CLI the second time causes it to produce an error. Variable wordpress_is_installed is registered for us here.

Install WordPress tables

Lastly, the WordPress database tables are installed with the wp core install WP-CLI command.

when: wordpress_is_installed|failed

This when condition utilizes a Jinja2 filter to check whether the previous task “Is WordPress installed?” failed. If it did, meaning the tables are not yet in the database, this task is run. It happens due to the fact that WP-CLI command line program exits with the status 1 (= error) when WordPress has not yet been installed.

vars/main.yml sample variables

As promised, here are some sample variables you can use in this role:

remote_deploy_user: deploy
remote_deploy_group: deploy
remote_deploy_home: /home/deploy

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

What’s next?

In the final article in the Ansible and WordPress series, I’ll explain to you how to set up and configure Nginx and HHVM with Ansible. A simple WordPress production server will be finished by that time.

Join the Conversation

1 Comment

  1. Awesome article; exactly what I needed. However, when I tried using your configuration, it would skip all the tasks with “when: wordpress_is_downloaded == False” which would then result in an error. The correct syntax is “when: wordpress_is_downloaded.stat.exists == False”. Thanks again!


Leave a comment

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

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

Facebook photo

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

Connecting to %s

%d bloggers like this: