01

Executive Summary

๐Ÿš€

Challenge

Legacy infrastructure with configuration drift, manual deployments, and unpredictable scaling costs hindering business agility.

๐Ÿ’ก

Solution

Cloud-native transformation using Azure with 100% IaC automation, dual-architecture benchmarking (PaaS vs IaaS).

โœ…

Results

97.8% faster deployments, 91.7% incident reduction, 89% cost savings with full environment parity.

Key Achievements

97.8%
Faster Deployments
4-6 hours โ†’ 8 minutes
100%
Environment Parity
Dev = Staging = Prod
91.7%
Incident Reduction
12 โ†’ 1 per month
5 min
Recovery Time
From 48 hours MTTR
graph LR subgraph Before["BEFORE: Legacy State"] A[Manual Deployments] --> B[Configuration Drift] B --> C[Environment Disparity] C --> D[Production Incidents] end subgraph After["AFTER: Cloud-Native"] E[IaC Automation] --> F[Immutable Infrastructure] F --> G[Environment Parity] G --> H[Zero-Downtime Deploys] end D -.->|Transformation| E
02

Strategic Objectives & KPIs

The primary mission was to move beyond simple "Lift and Shift" and achieve a "Cloud-Native" operational state.

Objective KPI Target Achieved Status
Infrastructure Reproducibility Automation Coverage 100% 100% โœ…
Performance Benchmarking Mean Latency <500ms 223ms โœ…
Cost Management Monthly Reduction 25% 32% โœ…
Security & Compliance RBAC Coverage 100% 100% โœ…
Deployment Frequency Deploys/Week 10+ 15 โœ…
MTTR Recovery Time <15min 5min โœ…
03

Technical Architecture Deep Dive

Two architectures were designed and benchmarked to determine the optimal approach for the organization's needs.

Architecture A

PaaS Model

Azure Web App for Containers

  • Compute: Linux App Service Plan (B1/S1)
  • Registry: Azure Container Registry
  • Identity: System-Assigned Managed Identity
  • Storage: Azure Files (Premium)
  • Networking: VNet Integration

โœ… Advantages

  • Zero server management
  • Built-in auto-scaling
  • Managed SSL/TLS
  • 99.95% SLA
Architecture B

IaaS Model

Ubuntu VM with Docker

  • Compute: Standard_B1s (1 vCPU, 1GB)
  • OS: Ubuntu Server 22.04 LTS
  • Storage: Premium SSD (LRS)
  • Network: VNet + NSG
  • Config: Ansible Automation

โœ… Advantages

  • Full kernel control
  • Lower latency (local SSD)
  • Custom networking
  • Flexible configuration

High-Level Architecture Comparison

graph TB subgraph PaaS["Architecture A: PaaS Model"] U1[Users] --> AFD1[Azure Front Door] AFD1 --> WAC[Web App for Containers] WAC --> ACR[Azure Container Registry] WAC --> MI[Managed Identity] MI --> KV1[Azure Key Vault] end subgraph IaaS["Architecture B: IaaS Model"] U2[Users] --> PIP[Public IP] PIP --> NSG[Network Security Group] NSG --> VM[Ubuntu 22.04 VM] VM --> DOCKER[Docker Engine] DOCKER --> APP[Laravel Container] end
04

Infrastructure as Code Implementation

Instead of monolithic scripts, the infrastructure was modularized for reusability and maintainability.

๐Ÿ“ Terraform Project Structure

terraform/
โ”œโ”€โ”€ environments/
โ”‚   โ”œโ”€โ”€ dev/
โ”‚   โ”œโ”€โ”€ staging/
โ”‚   โ””โ”€โ”€ prod/
โ”‚       โ”œโ”€โ”€ main.tf
โ”‚       โ”œโ”€โ”€ variables.tf
โ”‚       โ””โ”€โ”€ terraform.tfvars
โ”œโ”€โ”€ modules/
โ”‚   โ”œโ”€โ”€ network/      # VNet, Subnets, NSGs
โ”‚   โ”œโ”€โ”€ compute/      # VMs or App Service
โ”‚   โ””โ”€โ”€ storage/      # Managed Disks, Storage Accounts
โ”œโ”€โ”€ backend.tf        # Remote state config
โ””โ”€โ”€ versions.tf       # Provider versions

Network Module

# modules/network/main.tf

resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-vnet"
  address_space       = [var.vnet_address_space]
  location            = var.location
  resource_group_name = var.resource_group_name
  tags                = var.tags
}

resource "azurerm_network_security_group" "web" {
  name                = "${var.prefix}-nsg-web"
  location            = var.location
  resource_group_name = var.resource_group_name

  security_rule {
    name                       = "AllowHTTPS"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "DenyAllInbound"
    priority                   = 4096
    direction                  = "Inbound"
    access                     = "Deny"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

Compute Module (IaaS)

# modules/compute/main.tf

resource "azurerm_linux_virtual_machine" "main" {
  name                = "${var.prefix}-vm"
  resource_group_name = var.resource_group_name
  location            = var.location
  size                = var.vm_size
  admin_username      = var.admin_username

  network_interface_ids = [
    azurerm_network_interface.main.id,
  ]

  admin_ssh_key {
    username   = var.admin_username
    public_key = file(var.ssh_public_key_path)
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
    disk_size_gb         = 30
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts-gen2"
    version   = "latest"
  }

  identity {
    type = "SystemAssigned"
  }

  custom_data = base64encode(file("${path.module}/cloud-init.yaml"))
  tags        = var.tags
}

๐Ÿ–ฅ๏ธ Terraform Workflow Commands

# Initialize Terraform with remote backend
terraform init \
    -backend-config="resource_group_name=rg-terraform-state" \
    -backend-config="storage_account_name=stterraformstate"

# Validate configuration
terraform validate

# Plan changes (preview)
terraform plan -out=tfplan -var-file=environments/prod/terraform.tfvars

# Apply infrastructure changes
terraform apply tfplan

# Show current state
terraform show
05

CI/CD Pipeline Architecture

flowchart LR subgraph Source GH[GitHub Repository] end subgraph Build LINT[Linting & Tests] BUILD[Docker Build] SCAN[Security Scan] end subgraph Registry ACR[Azure Container Registry] end subgraph Deploy TF[Terraform Plan/Apply] ANS[Ansible Playbook] end subgraph Environments DEV[Development] STG[Staging] PRD[Production] end GH --> LINT --> BUILD --> SCAN --> ACR ACR --> TF --> ANS ANS --> DEV --> STG --> PRD

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: TerraCloud CI/CD Pipeline

on:
  push:
    branches: [main, develop]

jobs:
  build:
    name: Build & Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          
      - name: Install Dependencies
        run: composer install --no-interaction --prefer-dist
        
      - name: Run Tests
        run: php artisan test --coverage --min=80

  docker:
    name: Docker Build & Push
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ env.ACR }}/${{ env.IMAGE }}:${{ github.sha }}

  deploy:
    name: Deploy to Production
    needs: docker
    runs-on: ubuntu-latest
    steps:
      - name: Terraform Apply
        run: terraform apply -auto-approve
        
      - name: Ansible Playbook
        run: ansible-playbook playbooks/deploy.yml

Production Dockerfile

# Multi-stage build for security and size optimization
FROM composer:2.6 AS builder
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
COPY . .

FROM php:8.2-fpm-alpine AS production

# Security: Create non-root user
RUN addgroup -g 1001 -S web && \
    adduser -u 1001 -S web -G web

WORKDIR /var/www/html
COPY --from=builder --chown=web:web /app .

# Security: Run as non-root
USER 1001

HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget -q --spider http://localhost:8080/health

CMD ["php-fpm"]
06

Performance Benchmarking & Analysis

๐Ÿงช Testing Methodology

  • Tool: Apache Benchmark (ab)
  • Concurrent Users: 10
  • Total Requests: 1,000
  • Target: GET / (Homepage)
  • Iterations: 5 per architecture

Throughput Comparison

Latency Distribution

Comparative Performance Data

Metric PaaS (Web App) IaaS (VM) Difference
Throughput (req/s) 2.11 4.48 +112% IaaS
Mean Latency 474 ms 223 ms -53% IaaS
P95 Latency 892 ms 412 ms -54% IaaS
P99 Latency 1,234 ms 589 ms -52% IaaS
Failed Requests 0 0 Equal

โš ๏ธ I/O Bottleneck Discovery

The PaaS model showed higher latency due to network-attached storage for the SQLite database. The IaaS VM utilized local SSD throughput, providing significant I/O advantages.

07

Financial Analysis & TCO

Monthly Cost Distribution

Detailed Cost Breakdown

Component PaaS Environment IaaS Environment
Compute $12.41 (B1 Plan) $8.03 (B1s VM)
Storage Included $5.70 (32GB P10)
Networking (Public IP) Included $2.63/month
Container Registry $5.00 $5.00
Monitoring $2.50 $2.50
Management Overhead $0 (Managed) $150 (3h @ $50/hr)
TOTAL (Monthly) $19.91 $174.73

3-Year TCO Projection

PaaS Model

$716.76
3-Year Total

IaaS Model

$6,290.28
3-Year Total

PaaS Savings

89%
$5,573.52 saved
08

Security Implementation

graph TB subgraph Edge["Edge Security"] WAF[Web Application Firewall] FD[Azure Front Door] DDOS[DDoS Protection] end subgraph Network["Network Security"] NSG[Network Security Groups] VNET[Virtual Network] end subgraph Application["Application Security"] MI[Managed Identity] KV[Key Vault] TLS[TLS 1.3] end subgraph Data["Data Security"] ENC[Encryption at Rest] end WAF --> FD --> DDOS --> NSG --> VNET VNET --> MI --> KV --> TLS --> ENC
๐Ÿ”

Network Security Groups

Strict inbound/outbound rules with default deny policy.

๐ŸŽญ

Managed Identity

Zero hardcoded credentials with system-assigned identities.

๐Ÿ”‘

RBAC Policies

Principle of Least Privilege with custom role definitions.

๐Ÿ›ก๏ธ

DDoS Protection

Azure-native DDoS mitigation at the network edge.

09

Recommendations & Scaling Roadmap

Phase 1

Database Migration

2 weeks

Migrate SQLite to Azure Database for MySQL (Flexible Server) to eliminate I/O bottlenecks.

Phase 2

Global Load Balancing

3 weeks

Implement Azure Front Door for CDN capabilities and WAF protection.

Phase 3

Cost Optimization

2 weeks

Implement Reserved Instances for 30-60% additional savings over 1-3 year terms.

Phase 4

Multi-Region Deployment

4 weeks

Deploy to secondary region for disaster recovery and improved global latency.

10

Final Assessment

Key Takeaway

The TerraCloud project proves that "Standard" doesn't mean "Best."

While IaaS won the raw performance battle for this specific SQLite use case, the PaaS model offers a significantly more agile, secure, and cost-effective solution for modern business needs.

The implementation of IaC via Terraform ensures that this environment can be redeployed or scaled across regions in under 5 minutes.

Document Control

Version 2.1.0
Date January 14, 2026
Classification Internal Use Only
Review Cycle Quarterly