Ansible Tutorial: Deploy WordPress in multiple AWS EC2 hosts
In the fast-paced world of IT operations and system administration, managing infrastructure efficiently and securely is crucial to the success of any organization. As businesses grow, so does the complexity of their IT environments, making automation a key element in streamlining repetitive tasks and ensuring consistent results. Enter Ansible, a powerful open-source automation tool that has revolutionized the way IT teams manage and configure their systems.
Ansible, developed by Michael DeHaan and later acquired by Red Hat, is designed to simplify the process of automation by providing a clear and user-friendly interface for IT administrators. Unlike traditional configuration management tools, Ansible adopts a simple, agentless architecture, relying on SSH and Python to communicate with remote hosts. This unique approach has made Ansible one of the most popular automation tools in the DevOps ecosystem.
Here, I will demonstrate the setup of a WordPress site from an ansible control EC2 machine to multiple target hosts.
Step 1: Create instances for the ansible control machine and target hosts
Go to aws console and select EC2 service from the home
Click on launch instance
Name the instance
Select the Amazon Linux 2 as the ami
Create a key pair for all the instances
Name the key and create a .pem file for the purpose of connecting to the instance using SSH
Click on the Edit button on Network settings for setting up a security group with inbound ports 22 and 80.
Adding HTTP port so that we can access the WordPress website installed in target hosts from a browser using their public IP
Launch the instances
Rename the instances to identify ansible control machine from target hosts
Step2 : Connect to the instance designated as control node
Open Powershell in Windows machine, browse to the directory with the .pem file created during the launch process of the instance and connect to the instance using public DNS
Step 3: Set up ansible in control machine
Put in commands:
sudo yum update -y
sudo amazon-linux-extras install ansible2 -y
ansible --version
Step 4: Set up SSH from the control machine to target hosts
Browse to the /etc/ansible directory
We can see ansible.cfg, hosts and roles files
Here, the hosts file has the information of target hosts as we will see later
For setting up target hosts from control machine first generate public key from control machine
Step 4A: Use the command :
ssh-keygen
It will create a public key in ~/.ssh directory of the control machine. Leave the answers empty for all the questions asked.
Step 4B: Create a .pem file in ~/.ssh directory
Browse to the .pem file on the local machine and open it.
Copy all of its contents
Paste the contents to the .pem file created in ~/.ssh directory
Press
Crtl+S and Ctrl+X
to save and exit from the nano editor.
Verify the contents using cat command with the .pem file.
Step 4C: set up ssh into the target machines using the following command
Here, the public key of the control machine is added to the “authorized_keys” of target hosts for the purpose of conducting ssh into those target machines.
cat ~/.ssh/id_rsa.pub | ssh -i ansible.pem ec2-user@<ip_of_individual_target_hosts> “cat >> ~/.ssh/authorized_keys”
For example,
cat ~/.ssh/id_rsa.pub | ssh -i ansible.pem ec2-user@44.212.25.235 “cat >> ~/.ssh/authorized_keys”
This will fail at first because we have not set up the hosts files so first we browse to /etc/ansible and open the hosts file in the nano editor
Set up the target hosts by uncommenting [webservers] and then adding the public IP addresses of the target hosts
Copy the public IP from target hosts
Paste
Ctrl+S and Ctrl+X
to save and exit the editor and try the commands again
Step 5: Create the playbook and run it
An Ansible playbook is a structured and human-readable YAML file used to define a series of tasks and configurations to be executed on remote hosts. Playbooks serve as the foundation of automation in Ansible and allow you to perform complex operations efficiently and consistently across your infrastructure. Each playbook consists of a set of plays, each with its own list of tasks.
Next, create .yml file that will be run by the ansible-playbook command.
As for the contents of the .yml file, I have a GitHub repository from where you can copy the template to set up WordPress websites in target hosts.
The code:
---
- name: Install LAMP stack and WordPress
hosts: webservers
become: true
tasks:
- name: Update packages
yum:
name: '*'
state: latest
update_cache: yes
- name: Install Apache
package:
name: httpd
state: present
- name: Start Apache service
service:
name: httpd
state: started
enabled: yes
- name: Install MariaDB
package:
name: mariadb-server
state: present
- name: Start MariaDB service
service:
name: mariadb
state: started
enabled: yes
- name: Enable php72 and epel repositories
become: yes
shell: amazon-linux-extras enable php7.2 epel
- name: Install PHP
package:
name: php
state: present
- name: Install PHP MySQLi extension
package:
name: php-mysqlnd
state: present
- name: Add ec2-user to apache group
user:
name: ec2-user
groups: apache
append: yes
- name: Set ownership for /var/www/ directory
file:
path: /var/www
owner: ec2-user
group: apache
state: directory
recurse: yes
- name: Set directory permissions
file:
path: /var/www
owner: root
group: apache
mode: '2775'
recurse: yes
state: directory
- name: Find all directories in /var/www
find:
paths: /var/www
file_type: directory
register: directories_to_set_permissions
- name: Set permissions for directories in /var/www
file:
path: "{{ item.path }}"
mode: "2775"
with_items: "{{ directories_to_set_permissions.files }}"
- name: Find all files in /var/www
find:
paths: /var/www
file_type: file
register: files_to_set_permissions
- name: Set permissions for files in /var/www
file:
path: "{{ item.path }}"
mode: "0664"
with_items: "{{ files_to_set_permissions.files }}"
- name: Install pymysql module for Python 3
package:
name: python3-pip
state: present
update_cache: yes
- name: Install pymysql module
pip:
name: pymysql
state: present
executable: pip3
- name: Create MySQL database
mysql_db:
name: wordpressdatabase
state: present
become: true
become_user: root
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Create MySQL user and give it privileges
mysql_user:
name: sanjeebuser
password: sanjeebpass
priv: "wordpressdatabase.*:ALL"
state: present
host: localhost
become: true
become_user: root
vars:
ansible_python_interpreter: /usr/bin/python3
- name: Flush MySQL privileges
command: mysql -e "FLUSH PRIVILEGES;"
become: true
become_user: root
- name: Download WordPress files
get_url:
url: "https://wordpress.org/latest.tar.gz"
dest: "/tmp/latest.tar.gz"
mode: "0644"
- name: Extract WordPress from archive
unarchive:
src: "/tmp/latest.tar.gz"
dest: "/var/www/html"
remote_src: yes
owner: ec2-user
group: apache
mode: "0640"
- name: Copy WordPress contents
copy:
src: /var/www/html/wordpress/
dest: /var/www/html/
remote_src: yes
- name: Rename wp-config-sample.php to wp-config.php
command: mv /var/www/html/wp-config-sample.php /var/www/html/wp-config.php
args:
creates: "/var/www/html/wp-config.php"
- name: Replace database name in wp-config.php
replace:
path: "/var/www/html/wp-config.php"
regexp: "database_name_here"
replace: "wordpressdatabase"
- name: Replace database username in wp-config.php
replace:
path: "/var/www/html/wp-config.php"
regexp: "username_here"
replace: "sanjeebuser"
- name: Replace database password in wp-config.php
replace:
path: "/var/www/html/wp-config.php"
regexp: "password_here"
replace: "sanjeebpass"
- name: Set directory permissions
file:
path: /var/www
owner: root
group: apache
mode: '2775'
recurse: yes
state: directory
- name: Find all directories in /var/www
find:
paths: /var/www
file_type: directory
register: directories_to_set_permissions
- name: Set permissions for directories in /var/www
file:
path: "{{ item.path }}"
mode: "2775"
with_items: "{{ directories_to_set_permissions.files }}"
- name: Find all files in /var/www
find:
paths: /var/www
file_type: file
register: files_to_set_permissions
- name: Set permissions for files in /var/www
file:
path: "{{ item.path }}"
mode: "0664"
with_items: "{{ files_to_set_permissions.files }}"
- name: Restart HTTPD service
service:
name: httpd
state: restarted
Paste the template in .yml file created inside /etc/ansible directory and then exit the editor.
Next, run the following command:
ansible-playbook wordpress.yml
Then all you do is wait until the procedure is completed.
After the command is completed, go to the console and copy the public IP of each target node separately and paste it into a new tab of your browser.
And here are the results.
First target machine
Second target machine
Third target machine
Author: Sanjeeb Nepal
https://www.linkedin.com/in/sanjeebnepal/