Automate Deploying a LAMP Stack Application using Ansible

A Cloud Enthusiast
Search for a command to run...

A Cloud Enthusiast
No comments yet. Be the first to comment.
DNS changes are powerful and risky. A single incorrect Route 53 record can cause outages, security exposure, or compliance issues. A simple but effective governance control is to get alerted whenever

Description Terraform is an infrastructure-as-code tool that makes handling infrastructure more straightforward and manageable. A Terraform module is a collection of configuration files that encapsula
Introduction Amazon Elastic Kubernetes Service (Amazon EKS) is a managed Kubernetes service that makes it easy for you to run Kubernetes on AWS and on-premises. Kubernetes is an open-source system for automating deployment, scaling, and management of...

In this article, I will briefly define what is DevOps, then we will discuss the suggested strategy to manage and automate DevOps teamwork in the context of AWS Team. What is DevOps? DevOps is the combination of cultural philosophies, practices, and t...
Introduction In this blog, we will demonstrate how to proactively monitor a web server EC2 security group for any traffic rule changes using Lambda along with a few other services. If we detect any unauthorized changes, we will then undo them using L...

Ansible is a software tool that provides simple but powerful automation for cross-platform computer support. It is primarily intended for IT professionals, who use it for application deployment, updates on workstations and servers, cloud provisioning, configuration management, intra-service orchestration, and nearly anything a systems administrator does on a weekly or daily basis. Ansible doesn't depend on agent software and has no additional security infrastructure, so it's easy to deploy.
In this project, we will use Ansible to deploy a LAMP stack web application on multi-node setup.
root privileges3 CentOS hosts on the same network. One will act the Ansible controller, and the other two will acts as target hosts. The hostnames should be configured as below to follow along:
Ansible installed on ansible-controller host
ansible-controller host is configured with the IP addresses of the targets as below example
mkdir lamp-stack-playbooks
cd lamp-stack-playbooks
vi inventory
[db_servers]
lamp-db ansible_host=<YOUR-DB-HOST-IP> ansible_user=<DB_USER> ansible_ssh_private_key_file=<PATH_TO_DB_SSH_PRIVATE_KEY> mysqlservice=mysqld mysql_port=3306 dbname=ecomdb dbuser=ecomuser dbpassword=ecompassword
[web_servers]
lamp-web ansible_host=<YOUR-WEB-HOST-IP> ansible_user=<WEB_USER> ansible_ssh_private_key_file=<PATH_TO_WEB_SSH_PRIVATE_KEY> httpd_port=80 repository=https://github.com/noweder/lamp-app-ecommerce.git
Create files sub-folder and move into it:
mkdir files
Create MySQL Configuration file my.cnf under files folder:
vi files/my.cnf
my.cnf and save it:[mysqld]
innodb-buffer-pool-size=5242880
# datadir=/var/lib/mysql
# socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
port=3306
db-load-script.sql on the controller host under files folder:vi files/db-load-script.sql
db-load-script.sql file and save it: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");
index.php file on controller host under files foldervi files/index.php
index.php file and make sure to replace <YOUR-DB-HOST-IP> with your specific DB Host IP address before saving it:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>E-Commerce Website</title>
<!-- Favicon -->
<link rel="icon" href="img/favicon.png" type="image/png" />
<!-- Bootstrap CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Icon CSS-->
<link rel="stylesheet" href="vendors/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="vendors/linearicons/linearicons-1.0.0.css">
<!-- Animations CSS-->
<link rel="stylesheet" href="vendors/wow-js/animate.css">
<!-- owl_carousel-->
<link rel="stylesheet" href="vendors/owl_carousel/owl.carousel.css">
<!-- Theme style CSS -->
<link href="css/style.css" rel="stylesheet">
<!-- <link href="css/responsive.css" rel="stylesheet"> -->
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!--==========Main Header==========-->
<header class="main_header_area">
<nav class="navbar navbar-default navbar-fixed-top" id="main_navbar">
<div class="container-fluid searchForm">
<form action="#" class="row">
<div class="input-group">
<span class="input-group-addon"><i class="lnr lnr-magnifier"></i></span>
<input type="search" name="search" class="form-control" placeholder="Type & Hit Enter">
<span class="input-group-addon form_hide"><i class="lnr lnr-cross"></i></span>
</div>
</form>
</div>
<div class="container">
<div class="row">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="col-md-2 p0">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">
<img src="img/logo.png" alt="">
<img src="img/logo-2.png" alt="">
</a>
</div>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<div class="col-md-9 p0">
<ul class="nav navbar-nav main_nav">
<li><a href="#">Laptops</a></li>
<li><a href="#">Drones</a></li>
<li><a href="#">Gadgets</a></li>
<li><a href="#">Phones</a></li>
<li><a href="#">VR</a></li>
<li><a href="#">Contact us</a></li>
</ul>
</div>
<div class="col-md-1 p0">
<ul class="nav navbar-nav navbar-right">
<li><a href="#" class="nav_searchFrom"><i class="lnr lnr-magnifier"></i></a></li>
</ul>
</div>
</div><!-- /.navbar-collapse -->
</div>
</div><!-- /.container-fluid -->
</nav>
</header>
<!--==========Main Header==========-->
<!--==========Slider area==========-->
<section class="slider_area row m0">
<div class="slider_inner">
<div class="camera_caption">
<h2 class="wow fadeInUp animated">Make Your Shopping Easy</h2>
<h5 class="wow fadeIn animated" data-wow-delay="0.3s">Find everything accordingly</h5>
<a class="learn_mor wow fadeInU" data-wow-delay="0.6s" href="#product-list">Show Now!</a>
</div>
</div>
</section>
<!--==========End Slider area==========-->
<section class="best_business_area row">
<div class="check_tittle wow fadeInUp" data-wow-delay="0.7s" id="product-list">
<h2>Product List</h2>
</div>
<div class="row it_works">
<?php
$link = mysqli_connect('<YOUR_DB_HOST_IP>', 'ecomuser', 'ecompassword', 'ecomdb');
if ($link) {
$res = mysqli_query($link, "select * from products;");
while ($row = mysqli_fetch_assoc($res)) { ?>
<div class="col-md-3 col-sm-6 business_content">
<?php echo '<img src="img/' . $row['ImageUrl'] . '" alt="">' ?>
<div class="media">
<div class="media-left">
</div>
<div class="media-body">
<a href="#"><?php echo $row['Name'] ?></a>
<p>Purchase <?php echo $row['Name'] ?> at the lowest price <span><?php echo $row['Price'] ?>$</span></p>
</div>
</div>
</div>
<?php
}
}
else {
?>
<div style="width: 100%">
<div class="error-content">
<h1>Database connection error</h1>
<p>
<?php
echo mysqli_connect_errno() . ":" . mysqli_connect_error();
?>
</p>
</div>
</div>
<?php
}
?>
</div>
</section>
<footer class="footer_area row">
<div class="container custom-container">
<div class="copy_right_area">
<h4 class="copy_right">© Copyright 2019 Ecommerce Website | All Rights Reserved</h4>
</div>
</div>
</footer>
<!-- jQuery -->
<script src="js/jquery-1.12.4.min.js"></script>
<!-- Bootstrap -->
<script src="js/bootstrap.min.js"></script>
<!-- Wow js -->
<script src="vendors/wow-js/wow.min.js"></script>
<!-- Wow js -->
<script src="vendors/Counter-Up/waypoints.min.js"></script>
<script src="vendors/Counter-Up/jquery.counterup.min.js"></script>
<!-- Stellar js -->
<script src="vendors/stellar/jquery.stellar.js"></script>
<!-- owl_carousel js -->
<script src="vendors/owl_carousel/owl.carousel.min.js"></script>
<!-- Theme js -->
<script src="js/theme.js"></script>
</body>
</html>
deploy-lamp-stack.yml playbook file under lamp-stack-playbooks and paste below code:---
- name: Deploy lamp stack application
hosts: all
become: yes
tasks:
- name: Install common dependencies
yum:
name:
- libselinux-python
- libsemanage-python
- firewalld
state: installed
# Install and Configure Database
- name: Deploy DB of the application
hosts: lamp-db
become: yes
tasks:
- name: Install MariaDB package
yum:
name:
- mariadb-server
- MySQL-python
state: installed
- name: Create Mysql configuration file
copy: src=files/my.cnf dest=/etc/my.cnf
- name: Start MariaDB Service
service: name=mariadb state=started enabled=yes
- name: Start firewalld
service: name=firewalld state=started enabled=yes
- name: insert firewalld rule
firewalld: port={{ mysql_port }}/tcp permanent=true state=enabled immediate=yes
- name: Create Application Database
mysql_db: name={{ dbname }} state=present
- name: Create Application DB User
mysql_user: name={{ dbuser }} password={{ dbpassword }} priv=*.*:ALL host='<YOUR_WEB_HOST_IP>' state=present
- name: Move db-load-script to db host
copy:
src: files/db-load-script.sql
dest: /tmp/db-load-script.sql
- name: Load Inventory Data
shell: mysql -f < /tmp/db-load-script.sql
- name: Deploy web application
hosts: lamp-web
become: yes
tasks:
- name: Install httpd and php
yum:
name:
- httpd
- php
- php-mysql
state: present
- name: Install web role specific dependencies
yum: name=git state=installed
- name: Start firewalld
service: name=firewalld state=started enabled=yes
- name: insert firewalld rule for httpd
firewalld: port={{ httpd_port }}/tcp permanent=true state=enabled immediate=yes
- name: Set index.php as the default page
tags: "Set index.php as the default page"
replace:
path: /etc/httpd/conf/httpd.conf
regexp: 'DirectoryIndex index.html'
replace: 'DirectoryIndex index.php'
- name: http service state
service: name=httpd state=started enabled=yes
- name: Copy the code from repository
git: repo={{ repository }} dest=/var/www/html/ force=yes
- name: Create the index.php file
copy: src=files/index.php dest=/var/www/html/index.php
<YOUR_WEB_HOST_IP> with your specific Web Host IP address before saving the file.ansible-playbook -i inventory deploy-lamp-stack.yml
host value <YOUR-WEB-HOST-IP> in Create Application DB User task with your specific web host IP address.curl <YOUR-WEB-HOST-IP>
<YOUR-WEB-HOST-IP> and paste it into a web browser.Thank you for reading!