How to Install and Set Up WordPress Using Ansible on CentOS 8

Install WordPress with Ansible

Installing and setting up the WordPress website is a very difficult task for any beginner user. You will need to perform a lot of things to set up WordPress website including, installing and configuring Apache, installing PHP, installing and configuring databases, and configuring the firewall.

You can automate the WordPress deployment process with the help of the Ansible. Server automation is an essential role for any system administrator. Ansible offers a simple architecture to automate the server deployment on hundreds or thousands of servers at a time.

In this tutorial, we will learn how to install and set up the WordPress website using Ansible on CentOS 8.

Prerequisites

  • One Ansible control node: A server running CentOS 8 with Ansible installed and configured. To set up Ansible, please follow my guide on How to Install and Setup Ansible.
  • One Ansible Target node: A fresh server running CentOS 8.
  • A valid domain name pointed with your server IP. In this tutorial, we will use wp.example.com.

Step 1: Create a Directory Structure

First, you will need to create a directory structure for the Ansible where all of your configurations will be stored.

Ansible directory structure

You can run the following commands to create a directory structure:

1
2
3
4
5
mkdir ~/wordpress
cd ~/wordpress
mkdir roles vars files
cd roles
mkdir -p apache/tasks php/tasks mysql/tasks wordpress/tasks firewall/tasks

After running the above commands. Your directory structure should look like the following:

1
tree ~/wordpress/

You should see the tree view of your directory structure.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
/root/wordpress/
├── files
├── roles
│   ├── apache
│   │   └── tasks
│   ├── firewall
│   │   └── tasks
│   ├── mysql
│   │   └── tasks
│   ├── php
│   │   └── tasks
│   └── wordpress
│       └── tasks
└── vars

Step 2: Create an Inventory File

Next, you will need to create an inventory file to define your Target host. You can create it with the following command:

1
nano ~/wordpress/inventory.txt

Add the following lines:

1
target1 ansible_host=192.168.0.11 ansible_user=root ansible_ssh_pass=admin@123

Save and close the file when you are finished.

Where:

  • ansible_host is the IP address of the Target host.
  • ansible_user is the root user of the Target host.
  • ansible_ssh_pass is the password of the root user on the Target host.

Step 3: Create an Ansible Variable

Next, you will need to define a variable to store the information about common things including, MySQL user, Apache host, Port, Password, PHP extensions, etc. You can define the variables inside the vars file as shown below:

1
nano ~/wordpress/vars/default.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
13
#PHP Settings
php_modules: [ 'php', 'php-curl', 'php-gd', 'php-mbstring', 'php-xml', 'php-xmlrpc', 'php-soap', 'php-intl', 'php-zip' ]
#MySQL Settings
mysql_root_password: "your-root-password"
mysql_db: "wpdb"
mysql_user: "wpuser"
mysql_password: "password"
#HTTP Settings
http_host: "wp.example.com"
http_conf: "wp.example.com.conf"
http_port: "80"

Save and close the file when you are finished.

Where:

  • php_modules is the list of all PHP modules required for WordPress.
  • mysql_root_password is the MySQL root password that you want to set.
  • mysql_db is the database name of WordPress that you want to create.
  • mysql_user is the database user name of WordPress that you want to create.
  • mysql_password is the password of the MySQL user that you want to set.
  • http_host is the FQDN name of your WordPress website.
  • http_conf is the name of the WordPress configuration file.
  • http_port is the port of the Apache webserver.

Step 4: Create an Apache Virtual Host Template File

Next, you will need to create a template for Apache virtual host configuration. Ansible will copy this template file to the Target host.

You can create it inside the files directory:

1
nano ~/wordpress/files/httpd.conf

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<VirtualHost *:{{ http_port }}>
   ServerAdmin webmaster@localhost
   ServerName {{ http_host }}
   ServerAlias www.{{ http_host }}
   DocumentRoot /var/www/{{ http_host }}/wordpress
   ErrorLog /var/log/httpd/error.log
   CustomLog /var/log/httpd/access.log combined
   <Directory /var/www/{{ http_host }}/wordpress>
         Options Indexes FollowSymLinks
     AllowOverride all
     Require all granted
   </Directory>
</VirtualHost>

Save and close the file when you are finished.

Step 5: Create a Playbook for Apache Roles

Next, you will need to create a playbook for the Apache role to install and configure Apache on the Target host. This playbook will do the following things:

  • Install the Apache package.
  • Start the Apache service and enable it to start at boot.
  • Create an Apache web root directory.
  • Copy the Apache virtual host configuration template file from the Ansible control machine to the Ansible Target host.

You can create it inside the tasks directory as shown below:

1
nano ~/wordpress/roles/apache/tasks/main.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
- name: Install HTTP Packages
  yum: name=httpd update_cache=yes state=latest
- name: Start httpd service
  systemd: name=httpd state=started enabled=yes
- name: Create Apache Document Root
  file:
    path: "/var/www/{{ http_host }}"
    state: directory
    owner: "apache"
    group: "apache"
    mode: '0755'
- name: Set up Apache VirtualHost
  template:
    src: "files/httpd.conf"
    dest: "/etc/httpd/conf.d/{{ http_conf }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r

Save and close the file when you are finished.

Step 6: Create a Playbook for PHP Role

Next, you will need to create a playbook for the PHP role to install PHP and required PHP modules on the Target host. This playbook will do the following things:

  • Install PHP Remi repository.
  • Reset the default PHP repository and enable the Remi repository.
  • Install PHP and required modules.

You can create a playbook for PHP with the following command:

1
nano ~/wordpress/roles/php/tasks/main.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
- name: Install PHP Remi Repository
  yum: name=https://rpms.remirepo.net/enterprise/remi-release-8.rpm update_cache=yes state=latest
- name: Enable PHP Remi Repository
  command: dnf module reset php -y
  command: dnf module enable php:remi-7.4 -y
- name: Install PHP Extensions
  yum: name={{ item }} update_cache=yes state=latest
  loop: "{{ php_modules }}"

Save and close the file when you are finished.

Step 7: Create a Playbook for MySQL Role

Next, you will need to create a playbook for MySQL role to install and configure MySQL database on the Target host. This playbook will do the following things:

  • Install MySQL and other packages.
  • Start the MySQL service and enable it to start at boot.
  • Set the MySQL root password.
  • Create a database for WordPress.
  • Create a database user for WordPress.

You can create a playbook for MySQL with the following command:

1
nano ~/wordpress/roles/mysql/tasks/main.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# MySQL Configuration
    - name: Install MySQL Packages
      yum: name={{ item }} update_cache=yes state=latest
      loop: [ 'mysql-server', 'php-mysqlnd', 'python3-PyMySQL' ]
    - name: Start mysqld service
      systemd: name=mysqld state=started enabled=yes
    - name: Set MySQL root Password
      mysql_user:
        login_host: 'localhost'
        login_user: 'root'
        login_password: ''
        name: 'root'
        password: '{{ mysql_root_password }}'
        state: present
    - name: Creates database for WordPress
      mysql_db:
        name: "{{ mysql_db }}"
        state: present
        login_user: root
        login_password: "{{ mysql_root_password }}"
    - name: Create MySQL user for WordPress
      mysql_user:
        name: "{{ mysql_user }}"
        password: "{{ mysql_password }}"
        priv: "{{ mysql_db }}.*:ALL"
        state: present
        login_user: root
        login_password: "{{ mysql_root_password }}"

Save and close the file when you are finished.

Step 8: Create a Playbook for WordPress Role

Next, you will need to create a playbook for WordPress role to download and configure WordPress on the Target host. This playbook will do the following things:

  • Download and extract WordPress to the Apache web root directory.
  • Set ownership for WordPress.
  • Set permissions for directories.
  • Set permissions for files.
  • Rename WordPress sample configuration file.
  • Define database settings in the WordPress configuration file.
  • Restart the Apache service.

You can create a playbook for WordPress with the following command:

1
nano ~/wordpress/roles/wordpress/tasks/main.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# WordPress Configuration
    - name: Download and unpack latest WordPress
      unarchive:
        src: https://wordpress.org/latest.tar.gz
        dest: "/var/www/{{ http_host }}"
        remote_src: yes
        creates: "/var/www/{{ http_host }}/wordpress"
    - name: Set ownership
      file:
        path: "/var/www/{{ http_host }}"
        state: directory
        recurse: yes
        owner: apache
        group: apache
    - name: Set permissions for directories
      shell: "/usr/bin/find /var/www/{{ http_host }}/wordpress/ -type d -exec chmod 750 {} \\;"
    - name: Set permissions for files
      shell: "/usr/bin/find /var/www/{{ http_host }}/wordpress/ -type f -exec chmod 640 {} \\;"
    - name: Copy sample config file
      command: mv /var/www/{{ http_host }}/wordpress/wp-config-sample.php /var/www/{{ http_host }}/wordpress/wp-config.php creates=/var/www/{{ http_host }}/wordpress/wp-config.php
      become: yes
    - name: Update WordPress config file
      lineinfile:
        path: "/var/www/{{ http_host }}/wordpress/wp-config.php"
        regexp: "{{item.regexp}}"
        line: "{{item.line}}"
      with_items:
        - {'regexp': "define\\( 'DB_NAME', '(.)+' \\);", 'line': "define( 'DB_NAME', '{{mysql_db}}' );"}
        - {'regexp': "define\\( 'DB_USER', '(.)+' \\);", 'line': "define( 'DB_USER', '{{mysql_user}}' );"}
        - {'regexp': "define\\( 'DB_PASSWORD', '(.)+' \\);", 'line': "define( 'DB_PASSWORD', '{{mysql_password}}' );"}
    
    - name: Restart httpd service
      systemd: name=httpd state=restarted
      become: yes

Save and close the file when you are finished.

Step 9: Create a Playbook for Firewall Role

Next, you will need to create a playbook for Firewall role to disable the SELinux and configure Firewall on the Target host. This playbook will do the following things:

  • Disable the SELinux.
  • Disable the SELinux on the fly.
  • Configure the firewall to allow Apache service.
  • Reload the firewall rules.

You can create a playbook for the firewall with the following command:

1
nano ~/wordpress/roles/firewall/tasks/main.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
12
# Firewall Configuration
    - name: Disable SELinux Permanently (Reboot Required)
      selinux: state=disabled
    - name: Disable SELinux Without Reboot
      command: /sbin/setenforce 0
    - name: Configure Firewall
      firewalld: zone=public service=http permanent=yes state=enabled
    - name: Reload Firewall
      systemd: name=firewalld state=reloaded

Save and close the file when you are finished.

Step 10: Create a Main Playbook

Next, you will need to create a main playbook at the top of your project. This playbook includes all roles and variables that we have created earlier.

You can create a main playbook.yml file inside the ~/wordpress project directory:

1
nano ~/wordpress/playbook.yml

Add the following lines:

01
02
03
04
05
06
07
08
09
10
11
- hosts: target1
  gather_facts: False
  become: true
  vars_files:
    - vars/default.yml
  roles:
    - apache
    - php
    - mysql
    - wordpress
    - firewall

Save and close the file when you are finished.

Step 11: Run the Ansible Playbook

I hope you have performed all the above steps correctly. Now, change the directory to your ~/wordpress project and run the Ansible playbook with the following command:

1
2
cd ~/wordpress
ansible-playbook playbook.yml -i inventory.txt

This will install WordPress into your Target hosts. Once the playbook has been executed successfully, you should get the following output:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
PLAY [target1] ********************************************************************************************************************************
TASK [apache : Install HTTP Packages] *********************************************************************************************************
ok: [target1]
TASK [apache : Start httpd service] ***********************************************************************************************************
ok: [target1]
TASK [apache : Create Apache Document Root] ***************************************************************************************************
ok: [target1]
TASK [apache : Set up Apache VirtualHost] *****************************************************************************************************
ok: [target1]
TASK [php : Install PHP Remi Repository] ******************************************************************************************************
ok: [target1]
TASK [php : Enable PHP Remi Repository] *******************************************************************************************************
changed: [target1]
TASK [php : Install PHP Extensions] ***********************************************************************************************************
changed: [target1] => (item=php)
ok: [target1] => (item=php-curl)
changed: [target1] => (item=php-gd)
ok: [target1] => (item=php-mbstring)
ok: [target1] => (item=php-xml)
changed: [target1] => (item=php-xmlrpc)
changed: [target1] => (item=php-soap)
changed: [target1] => (item=php-intl)
changed: [target1] => (item=php-zip)
TASK [mysql : Install MySQL Packages] *********************************************************************************************************
changed: [target1] => (item=mysql-server)
changed: [target1] => (item=php-mysqlnd)
changed: [target1] => (item=python3-PyMySQL)
TASK [Start mysqld service] *******************************************************************************************************************
changed: [target1]
TASK [mysql : Set MySQL root Password] ********************************************************************************************************
changed: [target1]
TASK [mysql : Creates database for WordPress] *************************************************************************************************
changed: [target1]
TASK [mysql : Create MySQL user for WordPress] ************************************************************************************************
changed: [target1]
TASK [wordpress : Download and unpack latest WordPress] ***************************************************************************************
changed: [target1]
TASK [wordpress : Set ownership] **************************************************************************************************************
changed: [target1]
TASK [wordpress : Set permissions for directories] ********************************************************************************************
changed: [target1]
TASK [wordpress : Set permissions for files] **************************************************************************************************
changed: [target1]
TASK [wordpress : Copy sample config file] ****************************************************************************************************
changed: [target1]
TASK [wordpress : Update WordPress config file] ***********************************************************************************************
changed: [target1] => (item={'regexp': "define\\( 'DB_NAME', '(.)+' \\);", 'line': "define( 'DB_NAME', 'wpdb' );"})
changed: [target1] => (item={'regexp': "define\\( 'DB_USER', '(.)+' \\);", 'line': "define( 'DB_USER', 'wpuser' );"})
changed: [target1] => (item={'regexp': "define\\( 'DB_PASSWORD', '(.)+' \\);", 'line': "define( 'DB_PASSWORD', 'password' );"})
TASK [wordpress : Restart httpd service] ******************************************************************************************************
changed: [target1]
PLAY RECAP ************************************************************************************************************************************
target1                    : ok=19   changed=14   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
PLAY [target1] ********************************************************************************************************************************
TASK [firewall : Disable SELinux Permanently (Reboot Required)] *******************************************************************************
changed: [target1]
TASK [firewall : Disable SELinux Without Reboot] **********************************************************************************************
changed: [target1]
TASK [firewall : Configure Firewall] **********************************************************************************************************
changed: [target1]
TASK [firewall : Reload Firewall] *************************************************************************************************************
changed: [target1]
PLAY RECAP ************************************************************************************************************************************
target1                    : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Step 12: Access WordPress Installation Wizard

At this point, WordPress has been installed on the Target host. Now, open your web browser and type the URL https://wp.example.com. You will be redirected to the WordPress installation screen:

Select your desired language and click on the Continue button. You should see the following screen:

wordpress site details

Provide your Sitename, Username, Password, Email, and click on the Install WordPress button. Once the installation is completed, you should see the following screen:

wordpress install success

Click on the Log In button. You will be redirected to the WordPress login page:

wordpress login

Provide your admin username, password, and click on the Log In button. You should see the WordPress default dashboard in the following screen:

wordpress dashboard

You should also read the following chapters:
      1. Introduction
      2. Lab Setup – Install Ansible
      3. Ansible Inventory
      4. Introduction to YAML
      5. Ansible Playbooks
      6. Ansible Modules
      7. Ansible Variables
      8. Ansible Conditionals and Loops
      9. Ansible Roles

About Hitesh Jethva

I am Hitesh Jethva Founder and Author at LinuxBuz.com. I felt in love with Linux when i was started to learn Linux. I am a fan of open source technology and have more than 15+ years of experience in Linux and Open Source technologies.

View all posts by Hitesh Jethva