Infrastructure as Code

Modern DevOps Strategy

Manual server configuration is prone to error. By defining infrastructure as code (IaC), we can provision, configure, and deploy environments identically every time.

🏗️ Terraform:
Provisions the hardware (EC2, VPC, S3).

⚙️ Ansible:
Configures the software (Nginx, Docker, Users).

🚀 CI/CD:
Automates the testing and deployment pipeline.

Step 1: Terraform (Provisioning)

Instead of clicking buttons in the AWS Console, I use Terraform to define the entire cloud environment declaratively.

main.tf
provider "aws" {
  region = "us-east-1"
}

# 1. Create a Virtual Private Cloud (VPC)
resource "aws_vpc" "main_vpc" {
  cidr_block = "10.0.0.0/16"
}

# 2. Launch an EC2 Instance (Server)
resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0" # Ubuntu 20.04
  instance_type = "t2.micro"
  
  tags = {
    Name = "Portfolio-WebServer"
  }
}

# 3. Output the Public IP
output "server_ip" {
  value = aws_instance.web_server.public_ip
}

Key Benefits:

  • State Management: Terraform remembers what is already deployed (`terraform.tfstate`).
  • Idempotency: Running the script twice won't create two servers; it ensures the state matches the code.

Step 2: Ansible (Configuration)

Once the server exists, Ansible installs the software. It uses SSH to connect and run "Playbooks."

playbook.yaml
---
- name: Configure Web Server
  hosts: webservers
  become: true
  
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes

    - name: Install Nginx and Docker
      apt:
        name: 
          - nginx
          - docker.io
        state: present

    - name: Start Docker Service
      service:
        name: docker
        state: started
        enabled: yes

    - name: Copy Website Files
      copy:
        src: ./index.html
        dest: /var/www/html/index.html

Step 3: CI/CD Pipeline

I use GitHub Actions to automatically test and deploy code whenever I push to the repository.

🔄 The Workflow

  1. 1

    Push Code

    Developer commits change to GitHub.

  2. 2

    Test & Build

    GitHub Actions runs unit tests and builds Docker image.

  3. 3

    Deploy

    If tests pass, SSH into server and update container.

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

on:
  push:
    branches: [ "main" ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout Code
      uses: actions/checkout@v3

    - name: Build Docker Image
      run: docker build -t my-app .

    - name: Deploy via SSH
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          docker pull my-user/my-app:latest
          docker stop web-app || true
          docker rm web-app || true
          docker run -d -p 80:80 --name web-app my-user/my-app:latest