Production-inspired multi-environment AWS infrastructure using reusable Terraform modules, isolated remote state, tag-based IAM, and an approval-gated GitHub Actions deployment pipeline.
This project demonstrates how infrastructure can be promoted through Development → Staging → Production using Infrastructure as Code (IaC) while following governance practices commonly used in regulated environments.
Instead of maintaining three separate Terraform codebases, a single reusable module provisions each environment with different configurations, isolated state files, dedicated IAM permissions, and manual approval gates before higher-environment deployments.
Organizations operating in regulated industries (Banking, FinTech, Healthcare, Government) cannot deploy infrastructure directly into production.
Infrastructure changes should:
- follow a controlled promotion path
- isolate each environment
- enforce least-privilege permissions
- require human approval before production deployment
- maintain independent Terraform state
This project demonstrates that workflow using Terraform and GitHub Actions.
Reusable Terraform Module
modules/network
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
Development Staging Production
10.10.0.0/16 10.20.0.0/16 10.30.0.0/16
2 AZs 2 AZs 3 AZs
│ │ │
terraform-dev-role terraform-staging-role terraform-prod-role
│ │ │
dev.tfstate staging.tfstate prod.tfstate
│
▼
GitHub Actions Pipeline
deploy-dev
│
▼
Manual Approval
│
▼
deploy-staging
│
▼
Manual Approval
│
▼
deploy-prod
terraform-multi-env-iac/
│
├── modules/
│ └── network/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── environments/
│ ├── dev/
│ ├── staging/
│ └── prod/
│
├── iam/
│ ├── trust-policy.json
│ ├── dev-policy.json
│ ├── staging-policy.json
│ └── prod-policy.json
│
└── .github/
└── workflows/
└── deploy.yml
| Service | Purpose |
|---|---|
| Terraform | Infrastructure as Code |
| Terraform Modules | Reusable infrastructure components |
| Amazon VPC | Network isolation |
| Public & Private Subnets | Environment networking |
| Internet Gateway | Public connectivity |
| Route Tables | Network routing |
| Amazon S3 | Remote Terraform state |
| IAM | Least-privilege access |
| GitHub Actions | CI/CD pipeline |
| GitHub Environments | Manual deployment approvals |
- Reusable Terraform module
- Three isolated environments
- Independent Terraform state for every environment
- Tag-based IAM permissions
- Environment-specific IAM roles
- GitHub Actions deployment pipeline
- Manual approval gates for Staging and Production
- Environment promotion:
- Dev
- Staging
- Production
- Non-overlapping CIDR design
- Dynamic subnet creation using
countandcidrsubnet()
Developer Push
│
▼
GitHub Actions
│
▼
Deploy Development
│
▼
Manual Approval
│
▼
Deploy Staging
│
▼
Manual Approval
│
▼
Deploy Production
- Terraform
- AWS CLI
- Configured AWS credentials
- Amazon S3 backend
- GitHub repository secrets
Development
cd environments/dev
terraform init
terraform applyStaging
cd environments/staging
terraform init
terraform applyProduction
cd environments/prod
terraform init
terraform applyAny push affecting
modules/**
environments/**
automatically triggers the GitHub Actions pipeline.
Deployment flow:
Development
↓
Manual Approval
↓
Staging
↓
Manual Approval
↓
Production
Only one Terraform module is maintained.
Benefits:
- eliminates duplicated infrastructure code
- reduces configuration drift
- simplifies maintenance
The module requires:
- environment
- vpc_cidr
- azs
No defaults are used to avoid accidental environment overlap.
Subnets are generated using:
countcidrsubnet()
The same module supports:
- Dev (2 AZs)
- Staging (2 AZs)
- Production (3 AZs)
without modification.
A shared S3 bucket stores Terraform state.
Each environment uses an independent state key.
This prevents one environment from affecting another.
IAM permissions are controlled using the resource tag:
Environment
instead of resource name matching.
This provides cleaner least-privilege access and scales better as infrastructure grows.
GitHub Environments enforce approvals before:
- Staging
- Production
Development deploys automatically.
GitHub Actions uses job dependencies (needs) so environments are promoted in order:
Development
↓
Staging
↓
Production
Higher environments cannot deploy unless lower environments succeed.
The project was successfully validated for:
- Development deployment
- Staging deployment
- GitHub Environment approval gates
- Environment isolation
- Remote state isolation
- Independent IAM roles
During validation, the Production deployment approval gate functioned correctly. A subsequent deployment attempt encountered a temporary GitHub Actions service availability issue while downloading hosted runner actions. This was unrelated to the Terraform configuration or project implementation.
This project was designed with cost awareness.
Resources were:
- deployed
- verified
- destroyed
after testing.
The primary ongoing AWS cost was minimal Amazon S3 storage used for Terraform remote state.
Destroy each environment independently.
cd environments/dev
terraform destroycd environments/staging
terraform destroycd environments/prod
terraform destroyVerify cleanup:
aws ec2 describe-vpcs \
--region ap-south-2 \
--query 'Vpcs[?Tags[?Key==`Environment`]]'Expected result:
[]
- Build reusable modules instead of duplicating Terraform code.
- Separate Terraform state for every environment.
- Use resource tags to implement scalable least-privilege IAM.
- GitHub Environment approvals provide an effective deployment governance mechanism.
- Infrastructure promotion should be enforced by the pipeline rather than relying on manual process.
- Small CI/CD details (such as workflow path filters) can prevent pipelines from triggering correctly and are important to validate early.
- Terraform
- Infrastructure as Code
- Terraform Modules
- AWS Networking
- Amazon VPC
- IAM
- Amazon S3 Backend
- GitHub Actions
- CI/CD
- GitHub Environments
- Deployment Governance
- Multi-Environment Infrastructure
- Infrastructure Automation
- Cloud Architecture
Musaab Mohamedani
Cloud & DevOps Engineer
- GitHub: Mus7ab
- LinkedIn: Musaab Mohamedani