Learn how to install WordPress using Ansible on an Apache Server on PHP 7 with MySQL. As a DevOps Engineer, one of the main goals of our role is to automate. There are many reasons why we automate, but mine is to reduce human error and save time. In this guide, we’ll use many modules of Ansible which will speed up our job.
Note: Ansible has updated the references to the modules.
What will I learn?
- How to create a 100% working WordPress installation using the latest PHP version PHP7.
- How to enable the use of .htaccess file.
- How to create database, user and assigns the appropriate privileges.
- How to install the latest version of WordPress.
By the end of this guide, you’ll have mastered the art of WordPress automation using Ansible.
Prerequisites
- Access to a Ubuntu or Debian Linux Machine.
- Working SSH Connection to the server.
- Ansible working on the controller machine.
Let’s automate.
We will be creating four roles.
- Apache (Installing Apache 2.4, enabling the use of .htaccess)
- PHP (Installing PHP7 with the required extensions)
- MySQL (Installing MySQL 5.7)
- WordPress (Installing the latest WordPress version and configuring the wp-config.php
Step 1 – Installing Apache
The very first thing which we need to do is to install Apache so we could serve our website. This is extremely easy using the apt-get module. With the apt-get module, you can install any program.
In the first task, we’ll install Apache. In the second task, we’ll enable mod rewrite module. The mod rewrite module enables the use of .htaccess file.
- name: install apache
yum:
name: apache2
state: present
-name: Enable mod rewrite
apache2_module:
state: present
name: rewrite
- name: enable the use of .htaccess files in any projects
copy:
src: enable_htaccess.conf
dest: /etc/apache2/sites-available/enable_htaccess.conf
- name: enable the .htaccess vhost
file:
src: /etc/apache2/sites-available/enable_htaccess.conf
dest: /etc/apache2/sites-enabled/enable_htaccess.conf
state: link
In order to enable .htaccess file usage, will create “enable_htaccess.conf” in our files directory. The task above will copy the file into the Apache sites-available directory and enable it.
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
We use the state present to ensure we are only installing Apache if it has not been installed already. It is a good practice to mention the state while installing services.
Step 2 – Installing PHP
Now, that we have Apache working. It is time to install PHP. WordPress requires certain PHP extensions. We will be using the loop option of Ansible to install the required extensions. This makes it simpler and easier to customize.
name: install PHP
apt: name={{item}} state=present
with_items:
- php
- php-mcrypt
- php-mysql
- php-common
- php-mysql
- php-tidy
- php-xml
- php-xmlrpc
- php-mbstring
- php-memcached
- php-curl
- php-zip
Step 3 – Installing MySQL
The latest version of WordPress requires MySQL 5.7. We will use the package module to install MySQL
---
- name: Install MySQL Python
apt:
name: python-mysqldb
state: present
- name: install MySQL Server
apt:
name: mysql-server
state: present
- name: install MySQL Client
apt:
name: mysql-client
state: present
- name: install MySQL Common
apt:
name: mysql-common
state: present
- name: ensure MySQL always starts
service:
name: mysql
state: started
enabled: yes
Step 4 – Installing WordPress
Once, we have Apache, PHP and MySQL installed. Our final step is to download and install WordPress.
Since we are going to automate the entire process we have to create our wp-config variables.
Defining the variables:
Variables can be stored in many different places but we are going to save them in the defaults directory.
A good Ansible role is one which can easily be reused.
In the main.yml of defaults directory, place the below code.
--- # defaults file for wordpress wp_install_path : '/var/www' wp_directory_name: 'infinitypp' wp_db_name: 'name' wp_db_username: 'nm' wp_db_password: "22" wp_db_host: 'hos' wp_table_prefix: 'wpzcx_' wp_debug_mode: 'FALSE'
Writing the task.
In the wordpress/tasks/main.yml we’ll write our WordPress tasks. There are a few things which we need to check before proceeding. The most important of all is to ensure we’re not replacing a current working WordPress project. This is why we’ll only install WordPress if we ca’t find an index.php file in the install path.
- name: Concantenate the install and directory into a single variable
set_fact:
path: "{{wp_install_path}}/{{wp_directory_name}}"
- name: Only install WordPress when there is no index.php in the path
stat:
path: "{{path}}/index.php"
register: stat_result
- name: Ensure that installation directory exists
file: path={{path}} state=directory
when: stat_result.stat.exists == False
- name: Download Latest Version to /tmp
get_url: url=https://wordpress.org/latest.tar.gz force=no dest=/tmp/wordpress.tar.gz
when: stat_result.stat.exists == False
- name: Extract archive
unarchive: src=/tmp/wordpress.tar.gz dest=/tmp copy=no
when: stat_result.stat.exists == False
- name: Move extracted directory to {{path}}
shell: cp -r -n /tmp/wordpress/* {{path}}
when: stat_result.stat.exists == False
- name: Remove wordpress.tar.gz
file: path=/tmp/wordpress.tar.gz state=absent
when: stat_result.stat.exists == False
- name: Fetch random salts for WordPress config
local_action: command curl https://api.wordpress.org/secret-key/1.1/salt/
register: "wp_salt"
become: no
become_method: sudo
- name: Copy WordPress config file
template: src=wp-config.php dest={{path}}
- name: Change ownership of installation directory
file: path={{path}} owner=www-data group=www-data state=directory recurse=yes setype=httpd_sys_content_t
when: stat_result.stat.exists == False
- name: Change ownership of wp-content directory
file: path={{path}}/wp-content/ owner=www-data group=www-data mode=755 state=directory recurse=yes
when: stat_result.stat.exists == False
- name: Create a our WordPress database
mysql_db:
config_file: "/etc/mysql/my.cnf"
name: "{{wp_db_name}}"
state: present
- name: Create a new database user and password
mysql_user:
config_file: "/etc/mysql/my.cnf"
name: "{{wp_db_username}}"
password: "{{wp_db_password}}"
priv: '{{wp_db_name}}.*:ALL'
state: present
The last two task involves interaction with the database. It is a good practice to use vault to securely use our important variables.
Create wp-config.php in wordpress/templates directory
The wp-config.php variables will be replaced by the ones we declared in the main.yml (defaults) directory.
define('DB_NAME', '{{ wp_db_name }}');
define('DB_USER', '{{ wp_db_username }}');
define('DB_PASSWORD', '{{ wp_db_password }}');
define('DB_HOST', '{{ wp_db_host }}');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
{{ wp_salt.stdout }}
$table_prefix = '{{ wp_table_prefix }}';
define('WPLANG', '');
define('WP_DEBUG', {{ wp_debug_mode }});
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
require_once(ABSPATH . 'wp-settings.php');
Define our website, virtual host
Every website has a virtual host config. In-order to automate this process we’ll create vhost.conf.js in the wordpress/templates directory
This file will contain the virtual host config for our WordPress Website.
<VirtualHost>
DocumentRoot {{ path }}
ServerName {{ website_address }}
</VirtualHost>
If you visit the website URL mentioned in the variables configuration file, you will be prompted by the WordPress Insulation page. One of the good aspects of writing an Ansible role is its usability. If we want to deploy a WordPress website for another project, it is a matter of updating our variables
If you are looking into configuring cron jobs in Ansible, why not read our Ansible cron post
