Skip to content

This Terraform framework provides a comprehensive, production-ready infrastructure-as-code solution for AWS. Built with modularity, scalability, and multi-environment support at its core, it enables teams to manage complex AWS architectures across development, QA, and production environments using a single codebase and a single *.tfvars file.

License

Notifications You must be signed in to change notification settings

rajarshigit2441139/terraform-aws-infrastructure-framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Multi-environment, workspace-based AWS infrastructure management with modular Terraform

Terraform AWS License


πŸ“‹ Table of Contents


Overview

This Terraform framework provides a comprehensive, production-ready infrastructure-as-code solution for AWS. Built with modularity, scalability, and multi-environment support at its core, it enables teams to manage complex AWS architectures across development, QA, and production environments using a single codebase.

Key Principles

  • Workspace-Based Multi-Environment - Separate dev, QE, and prod using Terraform workspaces
  • DRY (Don't Repeat Yourself) - Reusable modules with consistent interfaces
  • Dynamic Resource Resolution - Automatic ID injection and reference resolution
  • Production-Ready - Battle-tested patterns and best practices
  • Cost-Aware - Built-in cost optimization strategies
  • Well-Documented - Comprehensive documentation for every module

Features

πŸ—οΈ Infrastructure Components

  • βœ… VPC Networking - Fully isolated virtual networks
  • βœ… Multi-AZ Subnets - Public, private, and database tiers
  • βœ… Internet & NAT Gateways - Managed internet connectivity
  • βœ… Route Tables - Dynamic routing with automatic gateway resolution
  • βœ… Security Groups - Firewall rules with SG-to-SG references
  • βœ… VPC Endpoints - Private AWS service connectivity (Gateway & Interface)
  • βœ… EKS Clusters - Managed Kubernetes control planes
  • βœ… EKS Node Groups - Worker nodes with launch templates
  • βœ… Elastic IPs - Static public IP addresses

πŸ”§ Framework Features

  • 🎯 Workspace Isolation - terraform workspace support for environment separation
  • πŸ”— Automatic Resource Linking - Modules reference each other by name, not ID
  • πŸ“¦ Modular Design - Each resource type is a self-contained module
  • 🏷️ Consistent Tagging - Automatic Name tags plus custom tag support
  • πŸ”„ State Management - Designed for remote state with locking
  • πŸ“Š Output Chaining - Structured outputs for cross-module dependencies
  • πŸ›‘οΈ Type Safety - Strongly-typed variables with validation
  • πŸ“ Comprehensive Docs - Module-level and root-level documentation

Architecture

High-Level Design

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Terraform Root                           β”‚
β”‚                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚  β”‚  Workspace   β”‚  β”‚  Workspace   β”‚  β”‚  Workspace   β”‚         β”‚
β”‚  β”‚   default    β”‚  β”‚      qe      β”‚  β”‚     prod     β”‚         β”‚
β”‚  β”‚    (dev)     β”‚  β”‚  (staging)   β”‚  β”‚ (production) β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚         β”‚                 β”‚                 β”‚                  β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚                           β”‚                                     β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚
β”‚         β”‚                                   β”‚                  β”‚
β”‚    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                         β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”             β”‚
β”‚    β”‚ VPC(s)  β”‚                         β”‚ EKS    β”‚             β”‚
β”‚    β”‚         β”‚                         β”‚Cluster β”‚             β”‚
β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”                  β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜             β”‚
β”‚    β”‚  β”‚   Subnets   β”‚                      β”‚                  β”‚
β”‚    β”‚  β”‚  Public /   β”‚                  β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚    β”‚  β”‚  Private    β”‚                  β”‚   Node     β”‚         β”‚
β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                  β”‚   Groups   β”‚         β”‚
β”‚    β”‚         β”‚                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”                                         β”‚
β”‚    β”‚  β”‚   Gateways  β”‚                                         β”‚
β”‚    β”‚  β”‚  IGW / NAT  β”‚                                         β”‚
β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                                         β”‚
β”‚    β”‚         β”‚                                                β”‚
β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”                                         β”‚
β”‚    β”‚  β”‚Route Tables β”‚                                         β”‚
β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                                         β”‚
β”‚    β”‚         β”‚                                                β”‚
β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”                                         β”‚
β”‚    β”‚  β”‚  Security   β”‚                                         β”‚
β”‚    β”‚  β”‚   Groups    β”‚                                         β”‚
β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                         β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Network Flow Example

                        Internet
                           β”‚
                           β–Ό
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   β”‚Internet Gatewayβ”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β”‚                             β”‚
        β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
        β”‚ Public  β”‚                   β”‚ Public  β”‚
        β”‚Subnet 1 β”‚                   β”‚Subnet 2 β”‚
        β”‚  (AZ1)  β”‚                   β”‚  (AZ2)  β”‚
        β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
            β”‚                             β”‚
      β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”               β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
      β”‚NAT Gateway β”‚               β”‚NAT Gateway β”‚
      β”‚    (AZ1)   β”‚               β”‚    (AZ2)   β”‚
      β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
            β”‚                             β”‚
        β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
        β”‚ Private β”‚                   β”‚ Private β”‚
        β”‚Subnet 1 β”‚                   β”‚Subnet 2 β”‚
        β”‚  (AZ1)  β”‚                   β”‚  (AZ2)  β”‚
        β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
            β”‚                             β”‚
       β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
       β”‚   EKS   β”‚                   β”‚   EKS   β”‚
       β”‚  Nodes  β”‚                   β”‚  Nodes  β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Available Infrastructure

Core Networking

Module Resource AWS Cost Purpose
VPC aws_vpc FREE Isolated virtual network
Subnet aws_subnet FREE Network segmentation (public/private)
Internet Gateway aws_internet_gateway FREE Internet access for public subnets
NAT Gateway aws_nat_gateway $32.40/mo Internet access for private subnets
Route Table aws_route_table FREE Traffic routing rules
Elastic IP aws_eip FREE* Static public IP addresses

*FREE when attached; $3.60/month when idle

Security

Module Resource AWS Cost Purpose
Security Group aws_security_group FREE Virtual firewall rules
Security Rules aws_vpc_security_group_*_rule FREE Ingress/egress traffic control

VPC Connectivity

Module Resource AWS Cost Purpose
Gateway Endpoint aws_vpc_endpoint (Gateway) FREE Private S3/DynamoDB access
Interface Endpoint aws_vpc_endpoint (Interface) $7.30/mo Private AWS service access

Container Orchestration

Module Resource AWS Cost Purpose
EKS Cluster aws_eks_cluster $73/mo Managed Kubernetes control plane
EKS Node Group aws_eks_node_group Variable* Kubernetes worker nodes

*Node group cost = EC2 instance costs (e.g., t3.medium = $30/month)

Complete Infrastructure Modules

modules/
β”œβ”€β”€ vpc/                     # VPC creation
β”œβ”€β”€ subnet/                  # Subnet management
β”œβ”€β”€ igw/                     # Internet Gateway
β”œβ”€β”€ nat_gw/                  # NAT Gateway
β”œβ”€β”€ rt/                      # Route Tables
β”œβ”€β”€ eip/                     # Elastic IPs
β”œβ”€β”€ security_group/          # Security Groups & Rules
β”œβ”€β”€ vpc_endpoint/            # VPC Endpoints
└── eks_mng/
    β”œβ”€β”€ eks_cluster/        # EKS Control Plane
    └── eks_nodegroups/     # EKS Worker Nodes

Monthly Cost Estimates

Development Environment:

1 VPC                 = FREE
4 Subnets             = FREE
1 Internet Gateway    = FREE
1 NAT Gateway         = $32.40
2 Route Tables        = FREE
2 Security Groups     = FREE
1 EKS Cluster         = $73.00
2 t3.small nodes      = $30.00
─────────────────────────────
Total                 β‰ˆ $135.40/month

Production Environment (HA):

1 VPC                 = FREE
9 Subnets (3 AZs)     = FREE
1 Internet Gateway    = FREE
3 NAT Gateways        = $97.20
5 Route Tables        = FREE
5 Security Groups     = FREE
3 EKS Clusters        = $219.00
10 t3.medium nodes    = $300.00
─────────────────────────────
Total                 β‰ˆ $616.20/month

Quick Start

Prerequisites

  • Terraform >= 1.0
  • AWS CLI configured with credentials
  • AWS account with appropriate IAM permissions
  • Basic understanding of AWS networking and Terraform

Installation

# Clone the repository
git clone <repository-url>
cd terraform-aws-infrastructure-framework

# Initialize Terraform
terraform init

# Create workspace for your environment
terraform workspace new dev
terraform workspace select dev

Configuration

  1. Copy example configuration:
cp examples/mini_test.tfvars terraform.tfvars
  1. Edit terraform.tfvars with your configuration:
# VPC Configuration
vpc_parameters = {
  default = {
    my_vpc = {
      cidr_block = "10.10.0.0/16"
      tags = {
        Environment = "dev"
        Project     = "my-project"
      }
    }
  }
}

# Subnet Configuration
subnet_parameters = {
  default = {
    public_subnet_az1 = {
      cidr_block              = "10.10.1.0/24"
      vpc_name                = "my_vpc"
      az_index                = 0
      map_public_ip_on_launch = true
      tags                    = { Type = "public" }
    }

    private_subnet_az1 = {
      cidr_block              = "10.10.10.0/24"
      vpc_name                = "my_vpc"
      az_index                = 0
      map_public_ip_on_launch = false
      tags                    = { Type = "private" }
    }
  }
}

Deployment

# Validate configuration
terraform validate

# Preview changes
terraform plan

# Deploy infrastructure
terraform apply

# View outputs
terraform output

Verification

# Check created resources
terraform show

# Verify VPC
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=my_vpc"

# Verify subnets
aws ec2 describe-subnets --filters "Name=vpc-id,Values=<vpc-id>"

# Check EKS cluster (if deployed)
aws eks describe-cluster --name <cluster-name>

Project Structure

.
β”œβ”€β”€ README.md                          # This file 
β”œβ”€β”€ CHANGELOG.md  
β”œβ”€β”€ CONTRIBUTORS.md                          
β”œβ”€β”€ SECURITY.md                        # Project security report 
β”œβ”€β”€ LICENSE 
β”œβ”€β”€ terraform.tfvars                   # User configuration (git-ignored)
β”œβ”€β”€ variables.tf                       # Root variable definitions
β”œβ”€β”€ outputs.tf                         # Root outputs
β”œβ”€β”€ provider.tf                        # AWS provider configuration
β”‚
β”œβ”€β”€ 01_locals.tf                       # Local value transformations
β”œβ”€β”€ 02_vpc.tf                          # VPC module calls
β”œβ”€β”€ 03_subnet.tf                       # Subnet module calls
β”œβ”€β”€ 04_rt.tf                           # Route Table module calls
β”œβ”€β”€ 05_security_group.tf               # Security Group module calls
β”œβ”€β”€ 06_eip.tf                          # Elastic IP module calls
β”œβ”€β”€ 07_eks.tf                          # EKS Cluster module calls
β”œβ”€β”€ 08_gateway.tf                      # IGW, NAT Gateway module calls
β”œβ”€β”€ 09_vpc_endpoint.tf                 # VPC Endpoint module calls
β”‚
β”œβ”€β”€ backendfiles/                      # Backend configuration files
β”‚   β”œβ”€β”€ backend.default.conf.demo
β”‚   β”œβ”€β”€ backend.prod.conf
β”‚   └── backend.qe.conf
β”‚
β”œβ”€β”€ docs/                              # Documentation
β”‚   β”œβ”€β”€ GETTING_STARTED.md
β”‚   β”œβ”€β”€ NETWORKING.md
β”‚   β”œβ”€β”€ NETWORK_SECURITY.md
β”‚   β”œβ”€β”€ VPC_ENDPOINTS.md
β”‚   β”œβ”€β”€ EKS.md
β”‚   β”œβ”€β”€ EXAMPLE.md
β”‚   β”œβ”€β”€ TROUBLESHOOTING.md
β”‚   └── COST_OPTIMIZATION.md
β”‚ 
β”œβ”€β”€ examples/
β”‚    β”œβ”€β”€ all_example.tfvars
β”‚    β”œβ”€β”€ mini_test.tfvars 
β”‚    └── pub_test.tfvars 
β”‚
└── modules/                           # Reusable modules
    β”œβ”€β”€ vpc/
    β”‚   β”œβ”€β”€ main.tf
    β”‚   β”œβ”€β”€ variables.tf
    β”‚   β”œβ”€β”€ outputs.tf
    β”‚   └── README.md
    β”œβ”€β”€ subnet/
    β”œβ”€β”€ rt/
    β”œβ”€β”€ igw/
    β”œβ”€β”€ nat_gw/
    β”œβ”€β”€ eip/
    β”œβ”€β”€ security_group/
    β”œβ”€β”€ vpc_endpoint/
    └── eks_mng/
        β”œβ”€β”€ eks_cluster/
        └── eks_nodegroups/

    

Variable Structure

Overview: How Variables Work in This Framework

This framework uses a three-layer variable architecture with automatic resource ID injection and reference resolution:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    VARIABLE FLOW ARCHITECTURE                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Layer 1: USER INPUT (terraform.tfvars)
β”œβ”€ Workspace-scoped configuration
β”œβ”€ Human-readable resource names (not IDs)
β”œβ”€ Minimal required parameters
└─ Structure: map(map(object({...})))
           β”‚
           β–Ό
Layer 2: ROOT TRANSFORMATION 
β”œβ”€ Automatic ID injection
β”œβ”€ Reference resolution (names β†’ IDs)
β”œβ”€ Dynamic parameter generation
β”œβ”€ Workspace selection via lookup()
└─ Structure: Generated maps with injected IDs
           β”‚
           β–Ό
Layer 3: MODULE CONSUMPTION (modules/*/main.tf)
β”œβ”€ Receives fully-resolved parameters
β”œβ”€ Creates AWS resources
β”œβ”€ Returns outputs (IDs, ARNs, etc.)
└─ Structure: map(object({...})) with IDs

Data Type Structure

Root Variables Pattern

All root variables follow this structure:

variable "<resource>_parameters" {
  type = map(                           # Workspace level
    map(                                # Resource level
      object({                          # Configuration level
        # User-provided parameters (names, not IDs)
        <resource_name>   = string      # e.g., vpc_name, subnet_name
        <configuration>   = <type>      # Resource-specific config
        
        # Auto-injected by root (NOT provided by user)
        <resource_id>     = string      # e.g., vpc_id, subnet_ids
        
        tags = optional(map(string))
      })
    )
  )
}

Structure Breakdown:

  • First map: Workspaces (default, qe, prod)
  • Second map: Resource instances (unique identifiers)
  • Object: Resource configuration (parameters + auto-injected IDs)

Variable Transformation Pattern

Pattern 1: Simple ID Injection (VPC β†’ Subnet)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER INPUT (terraform.tfvars)                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

subnet_parameters = {
  default = {                          # ← Workspace
    my_subnet = {                      # ← Resource name
      cidr_block = "10.0.1.0/24"
      vpc_name   = "my_vpc"            # ← Human-readable reference
      az_index   = 0
    }
  }
}

          β”‚
          β”‚ Root Transformation
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GENERATED PARAMETERS                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

locals {
  generated_subnet_parameters = {
    for workspace, subnets in var.subnet_parameters :
    workspace => {
      for name, subnet in subnets :
      name => merge(subnet, {
        vpc_id            = local.vpc_id_by_name[subnet.vpc_name]
        # ────────────────  ──────────────────────────────────────
        #        β–²                          β–²
        #   Auto-injected            Lookup from VPC outputs
        
        availability_zone = data.aws_availability_zones.available.names[subnet.az_index]
        # ────────────────  ──────────────────────────────────────────────────────────
        #        β–²                                   β–²
        #   Auto-resolved                    AWS data source lookup
      })
    }
  }
}

          β”‚
          β”‚ Module Call (02_vpc.tf)
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MODULE RECEIVES (modules/subnet)                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

{
  cidr_block        = "10.0.1.0/24"
  vpc_id            = "vpc-0abc123def456"      # ← Injected ID
  availability_zone = "ap-south-1a"            # ← Resolved AZ
}

Pattern 2: List ID Injection (Subnets β†’ EKS Cluster)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER INPUT (terraform.tfvars)                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

eks_clusters = {
  default = {
    my_cluster = {
      cluster_version = "1.34"
      vpc_name        = "my_vpc"               # ← VPC name
      subnet_name     = ["sub1", "sub2"]       # ← Subnet names (list)
      sg_name         = ["cluster_sg"]         # ← Security group names
    }
  }
}

          β”‚
          β”‚ Root Transformation (07_eks.tf)
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GENERATED PARAMETERS                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

locals {
  generated_cluster_config = {
    for workspace, clusters in var.eks_clusters :
    workspace => {
      for name, cluster in clusters :
      name => merge(cluster, {
        vpc_id = local.vpc_id_by_name[cluster.vpc_name]
        
        subnet_ids = [
          for sn in cluster.subnet_name :
          local.subnet_id_by_name[sn]          # ← Loop through list
        ]
        # ────────────  ────────────────────
        #       β–²                β–²
        #  List of IDs    Lookup each name
        
        security_group_ids = [
          for sg in cluster.sg_name :
          local.sgs_id_by_name[sg]
        ]
      })
    }
  }
}

          β”‚
          β”‚ Module Call
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MODULE RECEIVES (modules/eks_mng/eks_cluster)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

{
  cluster_version    = "1.34"
  vpc_id             = "vpc-0abc123"
  subnet_ids         = ["subnet-111", "subnet-222"]  # ← Injected list
  security_group_ids = ["sg-0abc123"]                # ← Injected list
}

Pattern 3: Cross-Module Reference (SG β†’ SG Rules)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER INPUT (terraform.tfvars)                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

ipv4_ingress_rule = {
  default = {
    web_from_alb = {
      vpc_name                   = "my_vpc"
      sg_name                    = "web_sg"    # ← Target SG (name)
      source_security_group_name = "alb_sg"    # ← Source SG (name)
      from_port                  = 80
      protocol                   = "TCP"
    }
  }
}

          β”‚
          β”‚ Root Transformation (03_security_group.tf)
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GENERATED PARAMETERS                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

locals {
  generated_ipv4_ingress_parameters = {
    for workspace, rules in var.ipv4_ingress_rule :
    workspace => {
      for name, rule in rules :
      name => merge(rule, {
        security_group_id = local.sgs_id_by_name[rule.sg_name]
        # ───────────────  ───────────────────────────────────
        #         β–²                      β–²
        #   Target SG ID          Lookup target by name
        
        referenced_security_group_id = local.sgs_id_by_name[rule.source_security_group_name]
        # ──────────────────────────  ─────────────────────────────────────────────────────
        #            β–²                                    β–²
        #      Source SG ID                      Lookup source by name
      })
    }
  }
}

          β”‚
          β”‚ Module Call
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MODULE RECEIVES (modules/security_group)                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

{
  security_group_id            = "sg-web123"   # ← Target SG ID
  referenced_security_group_id = "sg-alb456"   # ← Source SG ID
  from_port                    = 80
  protocol                     = "TCP"
}

ID Extraction Pattern

After module creates resources, IDs are extracted for use by other modules:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MODULE OUTPUT (modules/vpc/outputs.tf)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

output "vpcs" {
  value = {
    for key, vpc in aws_vpc.vpc_module:
    key => {
      name       = vpc.tags["Name"]
      id         = vpc.id                      # ← VPC ID
      cidr_block = vpc.cidr_block
    }
  }
}

          β”‚
          β”‚ Root Extraction 
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LOCAL VALUE EXTRACTION                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

locals {
  vpc_id_by_name = {
    for name, vpc in module.chat_app_vpc.vpcs :
    name => vpc.id
    # ──  ──────
    #  β–²      β–²
    # Key   Value
  }
}

# Result:
# {
#   "my_vpc"   = "vpc-0abc123"
#   "prod_vpc" = "vpc-0def456"
# }

          β”‚
          β”‚ Used by other modules
          β–Ό

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LOOKUP IN OTHER MODULES                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

vpc_id = local.vpc_id_by_name[subnet.vpc_name]
         # ──────────────────  ────────────────
         #         β–²                  β–²
         #   Lookup map        User-provided name

Complete Transformation Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 END-TO-END VARIABLE FLOW                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Step 1: USER CONFIGURATION
  terraform.tfvars
    - Workspace-scoped maps
    - Resource names (NOT IDs)
    - Minimal required parameters

Step 2: ROOT VARIABLE DEFINITIONS
  variables.tf
    - Type definitions
    - Workspace map structure
    - Validation rules

Step 3: MODULE OUTPUTS
  modules/*/outputs.tf
    - Export created resource IDs
    - Structured output maps

Step 4: LOCAL EXTRACTION
  01_locals.tf
    - Extract IDs from module outputs
    - Create name-to-ID lookup maps
    - Example: vpc_id_by_name, subnet_id_by_name

Step 5: LOCAL TRANSFORMATION
  01_locals.tf, 02_vpc.tf, etc.
    - Merge user config with auto-injected IDs
    - Resolve references (names β†’ IDs)
    - Generate final module parameters

Step 6: MODULE CONSUMPTION
  modules/*/main.tf
    - Receive fully-resolved parameters
    - Create AWS resources with IDs
    - Return outputs for next iteration

Key Concepts

Workspace Scoping

All variables use workspace-based scoping:

variable "<resource>_parameters" {
  type = map(           # ← Workspace level
    map(                # ← Resource level
      object({...})     # ← Configuration
    )
  )
}

# Usage in root:
lookup(var.<resource>_parameters, terraform.workspace, {} )
#      ────────────────────────  ────────────────────
#              β–²                          β–²
#       Variable name              Current workspace

Two-Phase Module Calls

Some modules require two separate calls:

# Phase 1: Create base resources (Security Groups)
module "security_group" {
  source = "./modules/security_group"
  security_group_parameters = lookup(...)
}

# Phase 2: Create dependent resources (Rules)
module "security_rules" {
  source            = "./modules/security_group"
  ipv4_ingress_rule = lookup(...)
  sg_name_to_id_map = local.sgs_id_by_name  # ← From Phase 1
  depends_on        = [module.security_group]
}

Dynamic vs Static Parameters

User Provides (Static):

  • Resource names (vpc_name, subnet_name)
  • Configuration values (cidr_block, instance_type)
  • Tags, ports, protocols

Framework Injects (Dynamic):

  • Resource IDs (vpc_id, subnet_ids)
  • Resolved values (availability_zone)
  • Cross-module references (security_group_ids)

Variable Documentation

For detailed variable schemas, see:

  • Root variables: variables.tf - Complete type definitions
  • Module variables: modules/*/variables.tf - Module-specific inputs
  • Module README: modules/*/README.md - Parameter descriptions and examples
  • Transformation logic: 01_locals.tf, 02_vpc.tf, etc. - Dynamic generation code
  • Usage examples: docs/EXAMPLES.md - Real-world configurations

Documentation

Quick Links

Document Description
Getting Started Initial setup, deployment, workspace management
Networking VPC, Subnets, Route Tables, Gateways
Security Security Groups, Rules, Best Practices
VPC Endpoints Gateway & Interface Endpoints
EKS EKS Clusters & Node Groups
Examples Complete architecture examples
Troubleshooting Common issues and solutions
Cost Optimization Cost-saving strategies

Module Documentation

Each module has comprehensive documentation:

  • Purpose & Use Cases
  • Input Variables
  • Output Values
  • Configuration Examples
  • Best Practices
  • Troubleshooting

See modules/<module>/README.md for module-specific docs.


Examples

Example 1: Basic Development Environment

# terraform.tfvars
vpc_parameters = {
  default = {
    dev_vpc = {
      cidr_block = "10.10.0.0/16"
      tags = { Environment = "dev" }
    }
  }
}

subnet_parameters = {
  default = {
    public_subnet = {
      cidr_block              = "10.10.1.0/24"
      vpc_name                = "dev_vpc"
      az_index                = 0
      map_public_ip_on_launch = true
    }
    
    private_subnet = {
      cidr_block = "10.10.10.0/24"
      vpc_name   = "dev_vpc"
      az_index   = 0
    }
  }
}

Result: Single-AZ development VPC with public and private subnets.

Example 2: Production Multi-AZ EKS

# terraform.tfvars (simplified)
eks_clusters = {
  prod = {
    prod_cluster = {
      cluster_version         = "1.34"
      vpc_name                = "prod_vpc"
      subnet_name             = ["pri_sub1", "pri_sub2", "pri_sub3"]
      sg_name                 = ["eks_cluster_sg"]
      endpoint_public_access  = false
      endpoint_private_access = true
      tags = { Environment = "prod" }
    }
  }
}

eks_nodegroups = {
  prod = {
    prod_cluster = {
      prod_nodes = {
        k8s_version    = "1.34"
        arch           = "arm64"
        min_size       = 3
        max_size       = 10
        desired_size   = 5
        instance_types = "t4g.medium"
        subnet_name    = ["pri_sub1", "pri_sub2", "pri_sub3"]
        node_security_group_names = ["eks_node_sg"]
        tags = { Tier = "application" }
      }
    }
  }
}

Result: Private EKS cluster with multi-AZ node groups using ARM instances.

Example 3: VPC with S3 Endpoint

vpc_endpoint_parameters = {
  default = {
    s3_endpoint = {
      region            = "ap-south-1"
      vpc_name          = "my_vpc"
      service_name      = "s3"
      vpc_endpoint_type = "Gateway"
      route_table_names = ["private_rt"]
      tags = { Purpose = "S3-Private-Access" }
    }
  }
}

Result: Free S3 access from private subnets without NAT Gateway costs.

See docs/EXAMPLES.md for complete architecture examples.


Cost Considerations

Free Resources

  • VPC, Subnets, Route Tables, Internet Gateway
  • Security Groups and Rules
  • Gateway Endpoints (S3, DynamoDB)
  • Elastic IPs (when attached)

Paid Resources

Resource Cost Optimization Tip
NAT Gateway $32.40/mo + $0.045/GB Use one per AZ (HA) or single for dev
EKS Cluster $73/mo Share clusters when possible
EC2 Nodes Variable Use ARM (t4g) for 20% savings
Interface Endpoints $7.30/mo + $0.01/GB Only for high-volume traffic
Idle Elastic IPs $3.60/mo Release immediately after use

Cost Optimization Strategies

  1. Development: Single NAT Gateway, shared EKS cluster
  2. Production: Multi-AZ NAT, separate EKS clusters per tier
  3. Use ARM instances (t4g) instead of x86 (t3) for ~20% savings
  4. VPC Endpoints for S3/DynamoDB (free Gateway endpoints)
  5. Cluster Autoscaler to scale nodes based on demand

See docs/COST_OPTIMIZATION.md for detailed strategies.


Contributing

Contributions are welcome! Please follow these guidelines:

How to Contribute

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make your changes
  4. Update documentation
  5. Test thoroughly
  6. Submit a pull request

Development Guidelines

  • Follow existing code style
  • Add tests for new features
  • Update module README.md files
  • Run terraform fmt before committing
  • Add examples for new configurations

Reporting Issues

  • Use GitHub Issues
  • Include Terraform version, AWS region, error messages
  • Provide minimal reproducible example
  • Check existing issues first

Support

Getting Help

  1. Documentation: Start with docs/ folder
  2. Module Docs: Check modules/<module>/README.md
  3. Examples: See docs/EXAMPLES.md
  4. Troubleshooting: Refer to docs/TROUBLESHOOTING.md
  5. Issues: Submit a GitHub issue

Useful Commands

# Workspace management
terraform workspace list
terraform workspace select <workspace>
terraform workspace new <workspace>

# Validation
terraform validate
terraform fmt -recursive
terraform plan

# Inspection
terraform state list
terraform show
terraform output

# Cleanup
terraform destroy

πŸ“„ License

This project is licensed under the Apache-2.0 license - see the LICENSE file for details.


πŸ™ Acknowledgments

  • AWS for comprehensive cloud services
  • HashiCorp for Terraform
  • Open-source community for best practices

πŸ“ˆ Roadmap

Current Version (1.0)

  • βœ… VPC, Subnets, Gateways(NAT,IGW), RoutTable, EIP
  • βœ… Security Groups
  • βœ… VPC Endpoints
  • βœ… EKS Clusters & Node Groups

πŸ“Š Project Status

  • Project Owner: rajarshigit2441139
  • Status: Active Development
  • Stability: Production-Ready (core modules)
  • Maintenance: Actively Maintained
  • Last Updated: January 2026

Built with ❀️ by the Infrastructure Team

Questions? Issues? Feedback?

About

This Terraform framework provides a comprehensive, production-ready infrastructure-as-code solution for AWS. Built with modularity, scalability, and multi-environment support at its core, it enables teams to manage complex AWS architectures across development, QA, and production environments using a single codebase and a single *.tfvars file.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published