Back to projects
TerraformAnsibleGitHub ActionsOPA/ConftestPackerAWSPythonBash

Infrastructure as Code Pipeline

Complete IaC pipeline with Terraform, Ansible, and GitHub Actions CI/CD featuring multi-environment workflow, OPA policy-as-code, Terratest, Infracost PR comments, and drift detection

5 min read

Overview

A complete Infrastructure as Code pipeline that provisions cloud infrastructure with Terraform, configures servers with Ansible, and automates the entire workflow through GitHub Actions CI/CD. Implements a multi-environment promotion flow (dev → staging → prod) with policy-as-code enforcement, cost estimation in PR comments, security scanning, infrastructure testing, and nightly drift detection.

This pipeline is designed to be the backbone of the portfolio — it provisions the VMs that run the Kubernetes cluster, the HA reverse proxy, and all other infrastructure components.

Key Features

Terraform Infrastructure

  • 7 reusable modules — VPC, compute, security-group, S3, DNS, IAM, RDS
  • 3 environments — dev (auto-deploy), staging (auto-deploy), prod (manual approval)
  • Remote state management — S3 backend with DynamoDB locking
  • Shared infrastructure — Common VPC, DNS zones, and state bucket (not environment-specific)
  • Production patterns — Proper tagging, variable validation, output descriptions

Ansible Configuration

  • 5 roles — common (hardening), webserver, database, docker, monitoring-agent
  • 6 playbooks — site (master), provision, webserver, database, security, maintenance
  • Idempotent execution — All playbooks safe to run multiple times
  • Jinja2 templates — SSH config, NGINX config, systemd units, Docker daemon config
  • CIS benchmark hardening — SSH lockdown, sysctl tuning, firewall, audit logging
  • Dynamic inventory — Generated from Terraform outputs

CI/CD Pipeline (GitHub Actions)

PR Pipeline (CI):

  1. Lint
    CODE
    terraform fmt -check
    ,
    CODE
    tflint
    ,
    CODE
    ansible-lint
  2. Security scan
    CODE
    tfsec
    ,
    CODE
    checkov
    ,
    CODE
    trivy
  3. Policy check — OPA/Conftest against Terraform plan
  4. Plan
    CODE
    terraform plan
    with output posted as PR comment
  5. Cost estimate — Infracost breakdown posted as PR comment

Deploy Pipeline (CD):

  1. Dev — Auto-deploy on merge to main
  2. Staging — Auto-deploy after dev succeeds
  3. Prod — Manual approval gate required
  4. Ansible — Configure servers post-provisioning
  5. Smoke tests — Verify deployment health

Policy-as-Code (OPA/Conftest)

  • VPC policy — Must have flow logs, /16 or smaller CIDR, at least 2 AZs
  • Compute policy — No public IPs (use NAT), approved instance types only, monitoring enabled
  • Storage policy — S3 must be encrypted, versioned, block public access, lifecycle rules
  • Security policy — No 0.0.0.0/0 on sensitive ports (22, 3389, 3306, 5432), descriptions required
  • Tagging policy — All resources must have Environment, Project, Owner, ManagedBy tags

Cost Management

  • Infracost integration — Cost estimate on every PR showing monthly cost change
  • Budget-aware policies — OPA rules rejecting expensive instance types
  • Right-sizing guidance — Dev uses small instances, staging medium, prod large

Drift Detection

  • Nightly scheduled job — Runs
    CODE
    terraform plan
    against live infrastructure
  • Alert on drift — Slack notification when out-of-band changes detected
  • Drift report — Detailed diff showing what changed outside of IaC

Architecture

CODE
1Developer → Git Push → PR Created 23 ┌───────────▼───────────────┐ 4 │ CI PIPELINE │ 5 │ │ 6 │ Lint → Security → Policy │ 7 │ → Plan → PR Comment Bot │ 8 │ (plan + infracost + │ 9 │ checkov findings) │ 10 └───────────┬───────────────┘ 1112 PR Approved & Merged 1314 ┌───────────▼───────────────┐ 15 │ CD PIPELINE │ 16 │ │ 17 │ Terraform Apply │ 18 │ → Ansible Playbooks │ 19 │ → Smoke Tests │ 20 └───────────┬───────────────┘ 2122 ┌───────────▼───────────────┐ 23 │ INFRASTRUCTURE │ 24 │ │ 25 │ DEV (auto) → STAGING │ 26 │ (auto) → PROD (manual) │ 27 └───────────────────────────┘

Technical Implementation

Terraform Module Design

Modules follow the standard structure with:

  • main.tf — Resource definitions with proper lifecycle management
  • variables.tf — Typed variables with descriptions, defaults, and validation blocks
  • outputs.tf — Meaningful outputs for cross-module references
HCL
1# Example: Security Group Module with dynamic rules 2resource "aws_security_group" "this" { 3 name = var.name 4 description = var.description 5 vpc_id = var.vpc_id 6 7 dynamic "ingress" { 8 for_each = var.ingress_rules 9 content { 10 from_port = ingress.value.from_port 11 to_port = ingress.value.to_port 12 protocol = ingress.value.protocol 13 cidr_blocks = ingress.value.cidr_blocks 14 description = ingress.value.description 15 } 16 } 17 tags = var.tags 18}

Environment Promotion Flow

  1. Developer opens PR with Terraform changes
  2. CI runs plan — developer reviews changes
  3. PR merged to
    CODE
    main
    → dev auto-deploys
  4. Dev smoke tests pass → staging auto-deploys
  5. Staging validated → production requires manual approval
  6. On approval → production deploys with Ansible configuration

Packer Image Building

Pre-baked AMIs reduce deployment time:

  • webserver.pkr.hcl — AMI with NGINX, Python, monitoring agents pre-installed
  • Base hardening — CIS benchmark applied at image level
  • Cleanup scripts — Zero disk blocks for smaller AMI sizes

Post-Deploy Validation

Smoke tests verify every deployment:

  • SSH connectivity to all provisioned instances
  • HTTP/HTTPS response verification on web servers
  • SSL certificate validity checks
  • Monitoring agent reporting status
  • Database connectivity and replication status

Deployment

First-Time Setup

Bash
1./scripts/bootstrap.sh # Install tools, configure backends 2./scripts/setup-backend.sh # Create S3 + DynamoDB for state

Daily Workflow

Bash
1# Make changes, create PR 2terraform plan # Preview changes 3# PR auto-runs full CI pipeline 4# After merge, CD deploys automatically

Drift Detection

Bash
1./scripts/drift-detect.sh # Manual drift check 2# Or: nightly GitHub Actions job runs automatically

Impact

  • 7 Terraform modules following best practices with typed variables and outputs
  • 3-environment promotion with manual prod approval gate
  • 5 OPA policies enforcing security, tagging, and cost governance
  • Infracost PR comments showing cost impact of every infrastructure change
  • Nightly drift detection catching out-of-band changes within 24 hours
  • Packer AMIs reducing deployment time from minutes to seconds
  • 8 GitHub Actions workflows covering the full CI/CD lifecycle
  • CIS-hardened servers via Ansible roles and Packer images

Future Plans

  • Add Terragrunt for DRY Terraform configuration across environments
  • Implement Terratest (Go) for automated infrastructure integration testing
  • Add Atlantis for self-service Terraform via PR comments
  • Integrate Bridgecrew/Palo Alto for continuous cloud security posture
  • Add multi-cloud support (GCP, Azure modules)
  • Implement GitOps for infrastructure with Flux/ArgoCD managing Terraform