Automating a Real-World 2-Tier Application Deployment on AWS Using Ansible

(Nginx + PHP-FPM + MariaDB | DevOps Project)

Introduction

In modern DevOps environments, manual server configuration is not scalable. Organizations rely on automation tools like Ansible to deploy, configure, and manage infrastructure efficiently.

In this blog, I will walk through a real-world 2-Tier Application Deployment on AWS using Ansible, where:

  • The Application Tier runs Nginx + PHP-FPM
  • The Database Tier runs MariaDB
  • Everything is deployed and managed using a single Ansible playbook

This is not a demo-level setup — it follows practical DevOps standards used in production environments.

Ansible-Based 2-Tier Application Architecture on AWS:-





What Is a 2-Tier Architecture?

2-Tier architecture separates the application into two logical layers:

Tier 1 — Application Server

  • Handles user requests
  • Runs web and application services
  • Exposed via public IP

Tier 2 — Database Server

  • Stores application data
  • Accessible only through private network
  • Not exposed to the internet

This separation improves:

  • Security
  • Maintainability
  • Scalability

Technology Stack Used

  • Cloud: AWS EC2 (Amazon Linux)
  • Automation: Ansible
  • Web Server: Nginx
  • Application Runtime: PHP + PHP-FPM
  • Database: MariaDB
  • OS: Amazon Linux 2023OS: Amazon Linux 2023
  • Access: SSH (Key-based authentication)

High-Level Architecture Flow

User
→ Browser
→ Public IP
→ App Server (Nginx + PHP-FPM)
→ Private Network
→ DB Server (MariaDB)

Ansible Control Node connects to both servers using SSH and automates all configuration steps.

Project Structure:-

ansible-project/
├── inventory.ini
├── 2-tier.yml
└── README.md
  • inventory.ini defines target servers
  • 2-tier.yml contains automation logic
  • README.md documents the project

Inventory Configuration (inventory.ini):-

[appservers]
172.31.44.42 ansible_user=ec2-user ansible_ssh_private_key_file=/home/ec2-user/terraform.pem

[dbservers]
172.31.32.96 ansible_user=ec2-user ansible_ssh_private_key_file=/home/ec2-user/terraform.pem

Why Inventory Is Important

  • Groups servers logically
  • Allows running different tasks on different tiers
  • Makes scaling easier (add more servers without changing playbooks)

Ansible Playbook — App Server Configuration

The first play configures the application server.

Key Tasks Performed

  1. Install required packages (Nginx, PHP, PHP-FPM)
  2. Start and enable services
  3. Deploy a PHP application file

App Server Code Snippet

- name: Installation and deployment on app server
hosts: appservers
become: yes

vars:
app_packages:
- nginx
- php
- php-fpm
app_services:
- nginx
- php-fpm
web_file_path: /usr/share/nginx/html/index.php

tasks:
- name: Install packages
dnf:
name: "{{ app_packages }}"
state: present

- name: Start services
systemd:
name: "{{ item }}"
state: started
enabled: true
loop: "{{ app_services }}"

- name: Deploy PHP app
copy:
dest: "{{ web_file_path }}"
content: |
<?php
phpinfo();
?>

Ansible Playbook — Database Server Configuration

The second play configures the database server.

Key Tasks Performed

  1. Install MariaDB server
  2. Start and enable database service
  3. Create application database

DB Server Code Snippet

- name: Installation and configuration of DB Server
hosts: dbservers
become: yes

vars:
db_package: mariadb105-server
db_service: mariadb
db_name: FCT

tasks:
- name: Install MariaDB
dnf:
name: "{{ db_package }}"
state: present

- name: Start DB service
systemd:
name: "{{ db_service }}"
state: started
enabled: true

- name: Create database
shell: mysql -u root -e "CREATE DATABASE IF NOT EXISTS {{ db_name }};"

Execution Command

Deployment is triggered using a single common :-

ansible-playbook -i inventory.ini 2-tier.yml

Ansible automatically:-

  • Connects to servers
  • Executes tasks in sequence
  • Ensures idempotency

Output Verification

After successful execution:

  • Ansible play recap shows no failures
  • PHP application is accessible via browser
  • Database is created successfully

Access URL:

http://<APP_SERVER_PUBLIC_IP>/index.php

if you see the PHP info page, the deployment is successful.

GitHub Repository

Repository Name
ansible-aws-2-tier-app-deployment:- click here

Add full source code and screenshots here.

About the Author

Mahesh Shelke
AWS | DevOps | Ansible | Linux | Terraform | Jenkins | Git | Github |


Press enter or click to view image in full size