An open API service indexing awesome lists of open source software.

https://github.com/devenes/web-server-provisioning

Provisioning a Web Server and a Database Server with a Dynamic Website Using Ansible
https://github.com/devenes/web-server-provisioning

ansible apache database sql terraform

Last synced: 11 months ago
JSON representation

Provisioning a Web Server and a Database Server with a Dynamic Website Using Ansible

Awesome Lists containing this project

README

          

# Provisioning a Web Server and a Database Server with a Dynamic Website Using Ansible

The purpose of this hands-on project is to have the knowledge of provisioning a web and database server with a dynamic website.

## Contents

- [Provisioning a Web Server and a Database Server with a Dynamic Website Using Ansible](#provisioning-a-web-server-and-a-database-server-with-a-dynamic-website-using-ansible)
- [Contents](#contents)
- [Project Setup](#project-setup)
- [Build the Infrastructure](#build-the-infrastructure)
- [Install Ansible on the Controller Node](#install-ansible-on-the-controller-node)
- [Pinging the Target Nodes](#pinging-the-target-nodes)
- [Install, Start and Enable MariaDB](#install-start-and-enable-mariadb)
- [Configure User Credentials and Database Schema](#configure-user-credentials-and-database-schema)
- [Install, Start and Enable Apache Web Server and Other Dependencies](#install-start-and-enable-apache-web-server-and-other-dependencies)
- [Pull the Code and Make Necessary Changes](#pull-the-code-and-make-necessary-changes)

## Project Setup

![ho-04](ho-04.png)

## Build the Infrastructure

- Get to the AWS Console and spin-up 3 EC2 Instances with `Red Hat Enterprise Linux 8` AMI.

- Configure the security groups as shown below:

- Controller Node ----> Port 22 SSH

- Target Node1 -------> Port 22 SSH, Port 3306 MYSQL/Aurora

- Target Node2 -------> Port 22 SSH, Port 80 HTTP

## Install Ansible on the Controller Node

- Connect to your `Controller Node`.

- Optionally you can connect to your instances using VS Code.

- Run the commands below to install Python3 and Ansible.

```bash
sudo yum install -y python3
```

```bash
pip3 install --user ansible
```

- Check Ansible's installation with the command below.

```bash
ansible --version
```

## Pinging the Target Nodes

- Run the command below to transfer your pem key to your Ansible Controller Node.

```bash
scp -i ec2-user@:/home/ec2-user
```

- Make a directory named `Ansible-Website-Project` under the home directory and cd into it.

```bash
mkdir Ansible-Website-Project
cd Ansible-Website-Project
```

- Create a file named `inventory.txt` with the command below.

```bash
vi inventory.txt
```

- Paste the content below into the inventory.txt file.

- Along with the hands-on, public or private IPs can be used.

-

DO NOT USE DNS NAMES AS THE ansible_host PROPERTY VALUE!

Because database server expects an ip number as a user's host name.

```txt
[servers]
db_server ansible_host= ansible_user=ec2-user ansible_ssh_private_key_file=~/
web_server ansible_host= ansible_user=ec2-user ansible_ssh_private_key_file=~/
```

- Create a file named `ping-playbook.yml` and paste the content below.

```bash
touch ping-playbook.yml
```

```yml
- name: ping them all
hosts: all
tasks:
- name: pinging
ping:
```

- Run the command below for pinging the servers.

```bash
ansible-playbook ping-playbook.yml -i inventory.txt
```

- Explain the output of the above command.

- Create another file named `ansible.cfg` in the project directory.

```
[defaults]
host_key_checking = False
inventory = inventory.txt
deprecation_warnings=False
interpreter_python=auto_silent
```

- Run the command below again.

```bash
ansible-playbook ping-playbook.yml
ansible all -m ping -o
```

## Install, Start and Enable MariaDB

- Create another file named `playbook.yml` under the `Ansible-Website-Project` directory.

- Paste the content below into the `playbook.yml` file.

```yml
- name: db configuration
hosts: db_server
tasks:
- name: install mariadb and PyMySQL
become: yes
yum:
name:
- mariadb-server
- python3-PyMySQL
state: latest

- name: start mariadb
become: yes
command: systemctl start mariadb

- name: enable mariadb
become: yes
systemd:
name: mariadb
enabled: true
```

- Explain what these 3 tasks and modules ([yum](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/yum_module.html), [command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html), [systemd](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/systemd_module.html)) do respectively.

- Explain how `become` property affects the task.

- Run the playbook.yaml

```bash
ansible-playbook playbook.yml
```

- Open up a new Terminal or Window and connect to the `db_server` instance and check if `MariaDB` is installed, started, and enabled.

```bash
mysql --version
```

- Create a file named `db-load-script.sql` under /home/ec2-user folder, copy and paste the content below.

```bash
vi db-load-script.sql
```

```txt
USE ecomdb;
CREATE TABLE products (id mediumint(8) unsigned NOT NULL auto_increment,Name varchar(255) default NULL,Price varchar(255) default NULL, ImageUrl varchar(255) default NULL,PRIMARY KEY (id)) AUTO_INCREMENT=1;

INSERT INTO products (Name,Price,ImageUrl) VALUES ("Laptop","100","c-1.png"),("Drone","200","c-2.png"),("VR","300","c-3.png"),("Tablet","50","c-5.png"),("Watch","90","c-6.png"),("Phone Covers","20","c-7.png"),("Phone","80","c-8.png"),("Laptop","150","c-4.png");
```

- Append the content below into `playbook.yml` file for transferring the sql script into database server.

```yml
- name: copy the sql script
copy:
src: ~/db-load-script.sql
dest: ~/
```

- Run the command below.

```bash
ansible-playbook playbook.yml
```

- Check if the file has been sent to the database server.

- Append the content below into `playbook.yml` file in order to login to db_server and set a root password.

```yml
- name: Create password for the root user
mysql_user:
login_password: ''
login_user: root
name: root
password: "devenes1234"
```

- Create a file named `.my.cnf` under home directory on controller node.

- Paste the content below.

```conf
[client]
user=root
password=devenes1234

[mysqld]
wait_timeout=30000
interactive_timeout=30000
bind-address=0.0.0.0
```

- Append the content below into `playbook.yml` file.

```yml
- name: copy the .my.cnf file
copy:
src: ~/.my.cnf
dest: ~/
```

- Run the command below and check if everything is ok.

```bash
ansible-playbook playbook.yml
```

## Configure User Credentials and Database Schema

- Append the content below into `playbook.yml` file in order to create a remote database user.

```yml
- name: Create db user with name 'remoteUser' and password 'devenes1234' with all database privileges
mysql_user:
name: remoteUser
password: "devenes1234"
login_user: "root"
login_password: "devenes1234"
priv: "*.*:ALL,GRANT"
state: present
host: "{{ hostvars['web_server'].ansible_host }}"
```

- Run the command below to check if everything is ok.

```bash
ansible-playbook playbook.yml
```

- Append the content below into `playbook.yml` file in order to create a database schema for the products table.

```yml
- name: Create database schema
mysql_db:
name: ecomdb
login_user: root
login_password: "devenes1234"
state: present
```

- Notice that this time the module name is `mysql_db`.

- Append the content below into `playbook.yml` file in order to check if the `products` table is already imported.

```yml
- name: check if the database has the table
shell: |
echo "USE ecomdb; show tables like 'products'; " | mysql
register: resultOfShowTables

- name: DEBUG
debug:
var: resultOfShowTables
```

- Explain what these shell commands do.

- Emphasize that we have a new property called `register`.

- Skip the explanation of the `register` property for now.

- Explain the output of the `debug module` **after running the playbook**.

- Append the content below int `playbook.yml` file in order to import the `products` table.

```yml
- name: Import database table
mysql_db:
name: ecomdb # This is the database schema name.
state: import # This module is not idempotent when the state property value is import.
target: ~/db-load-script.sql # This script creates the products table.
when: resultOfShowTables.stdout == "" # This line checks if the table is already imported. If so this task doesn't run.
```

- Explain that the previously registered task result `resultOfShowTable` has a property called stdout. Visit the [link](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html#return-values) to show the returns of the `shell` module.

- Explain that if the `resultofShowTables.stdout` gives null the database table will be imported. Otherwise, it won't be imported for not getting any error.

- Run the command below to check if there is an error.

```bash
ansible-playbook playbook.yml
```

- Connect to the database instance to check if there is a table named `products`.

- Run the command below.

```bash
echo "USE ecomdb; show tables like 'products'; " | mysql
```

- Append the content below in order to restart the MariaDB service.

```yml
- name: restart mariadb
become: yes
service:
name: mariadb
state: restarted
```

## Install, Start and Enable Apache Web Server and Other Dependencies

- Append the content below into the `playbook.yml` file

```yml
- name: web server configuration
hosts: web_server
become: yes
tasks:
- name: install the latest version of Git, Apache, Php, Php-Mysqlnd
package:
name:
- git
- httpd
- php
- php-mysqlnd
state: latest
```

- Emphasize that the `become` property can also be used at the play level.

- Explain that the `package` module has the functionality to employ whatever if the package manager is.

- Emphasize that the `Git, Apache Web Server, PHP, and Php-to-Mysql` packages will be installed.

- Append the content below into the `playbook.yml` file.

```yml
- name: start the server and enable it
service:
name: httpd
state: started
enabled: yes
```

- Explain that this block of configuration is used to start and enable the Apache Web Server.

## Pull the Code and Make Necessary Changes

- Append the content below into the `playbook.yml` file.

```yml
- name: clone the repo of the website
shell: |
if [ -z "$(ls -al /var/www/html | grep .git)" ]; then
git clone https://github.com/kodekloudhub/learning-app-ecommerce.git /var/www/html/
echo "ok"
else
echo "already cloned..."
fi
register: result

- name: DEBUG
debug:
var: result

- name: Replace a default entry with our own
lineinfile:
path: /var/www/html/index.php
regexp: '172\.20\.1\.101'
line: "$link = mysqli_connect('{{ hostvars['db_server'].ansible_host }}', 'remoteUser', 'devenes1234', 'ecomdb');"
when: not result.stdout == "already cloned..."
```

- For the first task, explain that;

- The first line checks if the result of the `ls -al /var/www/html | grep .git` command is null.
- The second line clones the project content into /var/www/html directory.

- Explain the output of the `debug module` **after running the playbook**.

- For the third task, explain that the `lineinfile` module finds the file specified in the path value, searches for the regular expression specified in the `regexp` property, and replaces the matching line with the value of the `line` property. But this task is run only if the standard output of the first task is not "already cloned...".

- Append the content below into `playbook.yml` file.

```yml
- selinux:
state: disabled

- name: Restart service httpd
service:
name: httpd
state: restarted
```

- Explain that we have to disable the `Security Enhanced Linux` in order to be able to query a remote database.

- Shortly explain that the SELinux is a Linux kernel security module that provides a mechanism for supporting access control security policies.

- Run the command below.

```bash
ansible-playbook playbook.yml
```

- Check if you can see the website on your browser.