Enterprise-Grade Azure Multi-Environment IaC
This Terraform configuration deploys a complete, production-ready infrastructure on Microsoft Azure. Our Infrastructure as Code (IaC) approach enables automated, repeatable, and consistent deployments across multiple environments (Dev, QA, UAT, Production).
Separate configurations for Dev, QA, UAT, and Production with complete isolation
Remote state in Azure Blob Storage with automatic locking and encryption
Reusable modules for all resources ensuring consistency and maintainability
Credentials via GitHub Secrets, NSG rules, and private network isolation
Our infrastructure follows a hub-and-spoke architecture with complete isolation between environments. Each environment contains its own Resource Group, Virtual Network, Storage Account, and Virtual Machines.
Multi-Environment Azure Infrastructure - Complete Isolation
Purpose: Logical container that holds related Azure resources for easy management, billing, and lifecycle control.
Example Names: rg-swarup-dev, rg-swarup-prod
Purpose: Cloud storage for files, blobs, and application data with encryption at rest and versioning enabled.
Purpose: Private network in Azure with custom IP addressing, completely isolated from other environments.
| Environment | VNet Address Space | Subnet Range |
|---|---|---|
| DEV | 10.0.0.0/16 |
10.0.1.0/24 |
| QA | 10.1.0.0/16 |
10.1.1.0/24 |
| UAT | 10.2.0.0/16 |
10.2.1.0/24 |
| PROD | 10.3.0.0/16 |
10.3.1.0/24 |
Purpose: Firewall rules that control inbound and outbound network traffic to protect VMs.
| Priority | Name | Port | Protocol | Action |
|---|---|---|---|---|
| 100 | AllowSSH | 22 | TCP | Allow |
| 110 | AllowHTTP | 80 | TCP | Allow |
| 120 | AllowHTTPS | 443 | TCP | Allow |
| 65000 | DenyAllInbound | * | * | Deny |
Purpose: Linux virtual server running Ubuntu 22.04 LTS with NGINX web server for hosting applications.
| Environment | VM Size | vCPUs | RAM | Cost/Month |
|---|---|---|---|---|
| DEV | Standard_B1s | 1 | 1 GB | ~$10 |
| QA | Standard_B1s | 1 | 1 GB | ~$10 |
| UAT | Standard_B2s | 2 | 4 GB | ~$25 |
| PROD | Standard_B2s | 2 | 4 GB | ~$50 |
Our Terraform project follows best practices with a modular architecture that promotes reusability, maintainability, and scalability.
Modular Terraform Project Structure
Terraform Project Organization - File Structure & Module Layout
Each module is self-contained with three key files:
main.tf - Resource definitionsvariables.tf - Input variablesoutputs.tf - Output values for other modulesTerraform state files are stored in Azure Blob Storage instead of local disk. This enables team collaboration, state locking, and disaster recovery.
Shared state accessible by entire team
Prevents concurrent modifications using Azure blob leases
State data encrypted at rest in Azure
Track changes and rollback if needed
Azure Blob Storage - Environment State File Organization
State Locking: Azure uses blob lease mechanism to lock state during terraform apply or terraform destroy, preventing concurrent modifications that could corrupt state.
Environment-specific configuration is managed through .tfvars files.
Same code, different values = different environments!
Terraform loads variables in this order (later overrides earlier):
variables.tfTF_VAR_*)terraform.tfvars (common values)secrets.auto.tfvars (gitignored secrets)environments/*.tfvars (environment-specific)| Variable | DEV | QA | UAT | PROD |
|---|---|---|---|---|
| vm_size | Standard_B1s |
Standard_B1s |
Standard_B2s |
Standard_B2s |
| storage_replication | LRS |
LRS |
GRS |
GRS |
| vnet_address | 10.0.0.0/16 |
10.1.0.0/16 |
10.2.0.0/16 |
10.3.0.0/16 |
| resource_group | rg-swarup-dev |
rg-swarup-qa |
rg-swarup-uat |
rg-swarup-prod |
# Deploy to DEV environment
terraform apply -var-file="environments/dev.tfvars"
# Deploy to QA environment
terraform apply -var-file="environments/qa.tfvars"
# Deploy to UAT environment
terraform apply -var-file="environments/uat.tfvars"
# Deploy to PRODUCTION environment
terraform apply -var-file="environments/prod.tfvars"
# Deploy Infrastructure
.\terraform\powershell\deploy.ps1 -Environment dev -Action apply
# Destroy Infrastructure
.\terraform\powershell\deploy.ps1 -Environment dev -Action destroy
# Plan Only (Review Changes)
.\terraform\powershell\deploy.ps1 -Environment prod -Action plan
# Initialize Terraform with Backend
terraform init -backend-config="key=terraform-dev.tfstate"
# Validate Configuration
terraform validate
# Format Code
terraform fmt -recursive
# Plan Changes
terraform plan -var-file="environments/dev.tfvars" -out=tfplan
# Apply with Plan File
terraform apply tfplan
# Apply with Auto-Approve (Careful!)
terraform apply -var-file="environments/dev.tfvars" -auto-approve
# Show Current State
terraform show
# List All Resources
terraform state list
# Destroy Everything
terraform destroy -var-file="environments/dev.tfvars"
# Trigger via GitHub UI:
# 1. Go to Actions tab
# 2. Select "Deploy Infrastructure" workflow
# 3. Click "Run workflow"
# 4. Select environment (dev/qa/uat/prod)
# 5. Choose action (apply/destroy)
# 6. Click "Run workflow"
# Automatic trigger on push to main:
git add .
git commit -m "Update infrastructure"
git push origin main
# Access Web Dashboard:
# 1. Open: https://your-website.azurewebsites.net/Terraform.html
# 2. Click "Deploy Infrastructure" button
# 3. Select Environment (DEV/QA/UAT/PROD)
# 4. Enter Security PIN
# 5. Click "Deploy Now"
# 6. Monitor progress in real-time
Use Terraform CLI or PowerShell scripts for rapid testing and iteration
GitHub Actions for automated, reviewed, and audited deployments
Dashboard for non-technical users with PIN protection
Always use plan before apply, require approvals for PROD
Sensitive credentials (VM passwords, Azure credentials) are never stored in code. Instead, they're securely managed through GitHub Secrets and injected at deployment time.
TF_VAR_* variables| Secret Name | Purpose | Used In |
|---|---|---|
AZURE_CLIENT_ID |
Azure Service Principal ID | OIDC Authentication |
AZURE_TENANT_ID |
Azure AD Tenant ID | OIDC Authentication |
AZURE_SUBSCRIPTION_ID |
Azure Subscription ID | OIDC Authentication |
VM_ADMIN_USERNAME |
VM Administrator Username | VM Creation |
VM_ADMIN_PASSWORD |
VM Administrator Password | VM Creation |
We use OpenID Connect (OIDC) instead of storing long-lived Azure credentials. GitHub generates short-lived JWT tokens that Azure validates, eliminating the need for stored secrets.
Local deployment with automated commands
CI/CD pipeline with environment protection
Visual interface with PIN protection
Direct command-line execution
terraform init -backend-config="key=terraform-dev.tfstate"terraform validateterraform plan -var-file="environments/dev.tfvars"terraform apply -var-file="environments/dev.tfvars"terraform outputInfrastructure Deployment Time: First deployment takes ~5-8 minutes. Subsequent updates take 2-3 minutes depending on changes.
Use modules for reusability and maintainability. Each module should have a single responsibility.
Always use remote state for team collaboration with proper locking mechanism.
Never commit secrets to git. Use GitHub Secrets or Azure Key Vault.
Tag all resources with environment, owner, and cost center for tracking.
Always run terraform plan and review changes before applying.
Keep all Terraform code in Git with meaningful commit messages.