This is a fully automated Ansible Playbook to setup a Wordpress website from scratch. This playbook will launch an EC2 instance with a keypair and a secuirty group with required rules and then install the latest Wordpress website for you.
- Install Ansible in Ansible Master server. Click here for Ansible Installation steps.
- Attach IAM EC2 role to the Ansible master instance. (You can also use AWS access_key and secret_key to connect to AWS. In this case, you have to specify access_key and secret_key in your playbook)
- While setting up the EC2 instance, the Playbook prompt you to enter AWS region, instance type, instance AMI id, your project name and name of SSH key.
- While installing Wordpress website, the Playbook prompt you to enter domain name, new root password for mysql, name for your wordpress database and database user name
- AWS IAM EC2 role is used instead of secret_key and access_key to connect to the AWS
- This main.yml file actually contains 2 paybooks; one for launching the instance in AWS and one for installing and setting up Wordpress.
-
with_items is used as a loop to delete files
Below tasks will generate an SSH keypair and copy private key(pem) to the working directory of Ansible master
- name: "SSH keypair creation. Keyname is {{key_name}}"
ec2_key:
region: "{{region}}"
name: "{{key_name}}"
state: present
register: "key_info"
- name: "copy private key to local server"
when: key_info.changed == true
copy:
content: "{{key_info.key.private_key}}"
dest: "./{{key_name}}.pem"
mode: "0400"
Below task will create a Security Group with ports 80,443,22 and 3306 opened
- name: "Create Security group"
ec2_group:
region: "{{region}}"
name: "{{project_name}}-sg"
description: "secuirty group for devops instance"
tags:
Name: "{{project_name}}-sg"
rules:
- proto: tcp
ports:
- 80
- 443
- 22
- 3306
cidr_ip: 0.0.0.0/0
cidr_ipv6: ::/0
rule_desc: "allow all on ports 80, 443, 3306 and 22"
rules_egress:
- proto: -1
ports: -1
cidr_ip: 0.0.0.0/0
cidr_ipv6: ::/0
register: "sg_info"
Below task will launch an EC2 instance of the submitted type using the submitted AMI id. The instance will use above created SSH key and Security Group.
- name: "Create EC2"
ec2:
region: "{{region}}"
key_name: "{{key_info.key.name}}"
instance_type: "{{type}}"
image: "{{ami_id}}"
wait: yes
group_id: "{{sg_info.group_id}}"
instance_tags:
Name: "{{project_name}}-webserver"
count_tag:
Name: "{{project_name}}-webserver"
exact_count: 1
register: ec2_info
Below task will create an in-memory inventory file with the access details of above created instance. Second playbook will use this in-memory inventory file to access the server for setting up LAMPStack and Wordpress.
- name: "Create Dynamic inventory"
add_host:
groups: "webserver"
hostname: "{{ ec2_info.tagged_instances[0].public_ip }}"
ansible_host: "{{ ec2_info.tagged_instances[0].public_ip }}"
ansible_user: "ec2-user"
ansible_port: 22
ansible_private_key_file: "{{key_name}}.pem"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
Below tasks will install Apache and PHP 7.4 in the server. Then copy virtualhost configuration from template in the Master to apache configuration directory in the server. This also creates a phpinfo() page in the document root of the domain and lastly restart and enable apache service
- name: "Install apache"
yum:
name:
- httpd
state: present
- name: "Install PHP 7.4"
shell: amazon-linux-extras install php7.4 -y
- name: "copy virtualhost from template"
template:
src: vhost.conf.tmpl
dest: /etc/httpd/conf.d/{{http_domain}}.conf
- name: "create document root for website"
file:
path: /var/www/html/{{http_domain}}/
state: directory
owner: "{{http_user}}"
group: "{{http_group}}"
- name: "create phpinfo page"
copy:
content: "<?php phpinfo(); ?>"
dest: /var/www/html/{{http_domain}}/phpinfo.php
owner: "{{http_user}}"
group: "{{http_group}}"
- name: "restart and enable apache service"
service:
name: httpd
state: restarted
Below tasks will install Mariadb-server in the server, set a password for mysql root user, remove test database and anonymous users. Then it will create a database for wordpress installation and a db user with full privileges on the created database.
- name: "Install mariadb"
yum:
name:
- mariadb-server
- MySQL-python
state: present
- name: "Restart and enable mariadb-server"
service:
name: mariadb
state: restarted
enabled: true
- name: "setting root password for mariadb"
ignore_errors: true
mysql_user:
login_user: "root"
login_password: ""
user: "root"
password: "{{db_root_password}}"
host_all: yes
- name: "remove anonymous users"
mysql_user:
login_user: "root"
login_password: "{{db_root_password}}"
user: ""
state: absent
- name: "remove test database"
mysql_db:
login_user: "root"
login_password: "{{db_root_password}}"
name: "test"
state: absent
- name: "create wordpress database"
mysql_db:
login_user: "root"
login_password: "{{db_root_password}}"
name: "{{wp_db}}"
state: present
- name: "create wordpress db user"
mysql_user:
login_user: "root"
login_password: "{{db_root_password}}"
name: "{{wp_db_user}}"
state: present
password: "{{wp_db_user_password}}"
priv: '{{wp_db}}.*:ALL'
This part of the Playbook will download the latest version of Wordpress from the internet to the server, extract it and move it to the document root with proper ownership. Then it will copy the content from wp-config template in the master and paste into the document root of the website. Lastly, it will remove unwanted files from /tmp, restart the services and display domain name and Public IP after completing the whole setup.
- name: "Download wordpress from Internet"
get_url:
url: "{{download_link}}"
dest: "/tmp/wordpress.tar.gz"
remote_src: true
- name: "extract tar file"
unarchive:
src: "/tmp/wordpress.tar.gz"
dest: "/tmp/"
remote_src: true
- name: "copy wordpress files from /tmp to docroot"
copy:
src: "/tmp/wordpress/"
dest: /var/www/html/{{http_domain}}/
owner: "{{http_user}}"
group: "{{http_group}}"
remote_src: true
- name: "configuring wp-config.php from template"
template:
src: wp-config.php.tmpl
dest: /var/www/html/{{http_domain}}/wp-config.php
owner: "{{http_user}}"
group: "{{http_group}}"
- name: "clean-up unwanted files"
file:
path: "{{item}}"
state: absent
with_items:
- "/tmp/wordpress"
- "/tmp/wordpress.tar.gz"
- name: "Final restart of apache"
service:
name: httpd
state: restarted
- name: "Print website details"
debug:
msg:
- "Your Wordpress website is ready. Please add below A RECORD in your DNS'"
- "NAME=====> {{http_domain}}"
- "TYPE=====> A"
- "VALUE====>{{ ansible_ssh_host }}"
- Run a syntax check
ansible-playbook main.yml --syntax-check
- Execute the Playbook
ansible-playbook main.yml
x------------------x---------------------x---------------------x-------------------x--------------------x---------------------x-------------------x