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