Production-ready Infrastructure as Code modules for AWS and Azure
This project showcases a comprehensive library of reusable Terraform modules designed for deploying production-grade infrastructure across AWS and Azure. The modules follow Infrastructure as Code (IaC) best practices, emphasizing modularity, reusability, and maintainability.
Each module is designed to be cloud-agnostic where possible, with consistent interfaces and documentation, enabling teams to provision infrastructure quickly while maintaining security and compliance standards.
Creates virtual networks with subnets, route tables, and security groups
Provisions VMs/EC2 instances with auto-scaling capabilities
Managed databases (RDS, Azure SQL) with backup and HA
Application and network load balancers with SSL termination
S3 buckets and Azure Blob Storage with lifecycle policies
EKS and AKS clusters with node pools and RBAC
Each module follows a consistent structure for ease of use and maintenance:
module-name/
├── main.tf # Primary resource definitions
├── variables.tf # Input variables with validation
├── outputs.tf # Output values
├── versions.tf # Provider version constraints
├── README.md # Module documentation
└── examples/ # Usage examples
├── basic/
└── advanced/
module "vpc" {
source = "./modules/aws/vpc"
environment = "production"
vpc_cidr = "10.0.0.0/16"
availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
enable_nat_gateway = true
enable_dns_hostnames = true
tags = {
Project = "MyApp"
ManagedBy = "Terraform"
Environment = "production"
}
}
variable "environment" {
description = "Environment name (dev, staging, production)"
type = string
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Environment must be dev, staging, or production."
}
}
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
default = "10.0.0.0/16"
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "Must be a valid IPv4 CIDR block."
}
}
variable "availability_zones" {
description = "List of availability zones"
type = list(string)
validation {
condition = length(var.availability_zones) >= 2
error_message = "At least 2 availability zones required for HA."
}
}
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "IDs of public subnets"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs of private subnets"
value = aws_subnet.private[*].id
}
output "nat_gateway_ips" {
description = "Elastic IPs of NAT Gateways"
value = aws_eip.nat[*].public_ip
}
resource "azurerm_resource_group" "main" {
name = "${var.project_name}-${var.environment}-rg"
location = var.location
tags = merge(
var.tags,
{
Environment = var.environment
ManagedBy = "Terraform"
}
)
}
resource "azurerm_virtual_network" "main" {
name = "${var.project_name}-${var.environment}-vnet"
address_space = [var.vnet_cidr]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tags = var.tags
}
resource "azurerm_subnet" "subnets" {
for_each = var.subnets
name = each.key
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [each.value.cidr]
service_endpoints = each.value.service_endpoints
}
module "azure_network" {
source = "./modules/azure/network"
project_name = "myapp"
environment = "production"
location = "East US"
vnet_cidr = "10.1.0.0/16"
subnets = {
web = {
cidr = "10.1.1.0/24"
service_endpoints = ["Microsoft.Storage"]
}
app = {
cidr = "10.1.2.0/24"
service_endpoints = ["Microsoft.Sql"]
}
data = {
cidr = "10.1.3.0/24"
service_endpoints = ["Microsoft.Storage", "Microsoft.Sql"]
}
}
tags = {
CostCenter = "Engineering"
Project = "WebApp"
}
}
All modules use remote state backends for team collaboration and state locking:
# AWS S3 Backend
terraform {
backend "s3" {
bucket = "terraform-state-prod"
key = "infrastructure/vpc/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
# Azure Storage Backend
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstatestorage"
container_name = "tfstate"
key = "infrastructure.tfstate"
}
}
# Validate configuration
terraform init
terraform validate
# Check formatting
terraform fmt -check -recursive
# Plan without apply
terraform plan -out=tfplan
# Security scanning
tfsec .
checkov -d .
Modules include automated tests using Terratest to verify functionality:
func TestVPCModule(t *testing.T) {
terraformOptions := &terraform.Options{
TerraformDir: "../examples/vpc",
Vars: map[string]interface{}{
"environment": "test",
"vpc_cidr": "10.99.0.0/16",
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
vpcID := terraform.Output(t, terraformOptions, "vpc_id")
assert.NotEmpty(t, vpcID)
}
Automated pipeline for testing and validating module changes:
name: Terraform Module CI
on:
pull_request:
paths:
- 'modules/**'
- '.github/workflows/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.0
- name: Terraform Format Check
run: terraform fmt -check -recursive
- name: Terraform Init
run: terraform init -backend=false
- name: Terraform Validate
run: terraform validate
- name: Run tfsec
uses: aquasecurity/[email protected]
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
This Terraform module library demonstrates proficiency in Infrastructure as Code principles, multi-cloud architecture, and DevOps best practices. The modules provide a solid foundation for rapid, consistent, and secure infrastructure deployment across cloud platforms.
The emphasis on reusability, validation, and automated testing ensures that infrastructure can be provisioned reliably and maintained effectively in production environments.