Skip to main content

📂 Terraform Directory Structure & Best Practices

A well-structured Terraform project improves maintainability, collaboration, and scalability. Below is a recommended directory structure:

📁 terraform-project/
├── 📁 modules/ # Reusable Terraform modules
│ ├── 📁 network/ # Networking-related resources
│ │ ├── main.tf # Resource definitions
│ │ ├── variables.tf # Input variables
│ │ ├── outputs.tf # Output values
│ ├── 📁 compute/ # Compute resources (EC2, VMs, etc.)
│ │ ├── main.tf # Resource definitions
│ │ ├── variables.tf # Input variables
│ │ ├── outputs.tf # Output values
├── 📁 environments/ # Environment-specific configurations
│ ├── 📁 dev/ # Development environment
│ │ ├── main.tf # Root module calling other modules
│ │ ├── variables.tf # Environment-specific variables
│ │ ├── backend.tf # Remote state backend configuration
│ ├── 📁 prod/ # Production environment
│ │ ├── main.tf # Root module calling other modules
│ │ ├── variables.tf # Environment-specific variables
│ │ ├── backend.tf # Remote state backend configuration
├── 📜 .terraform.lock.hcl # Lock file for module versions
├── 📜 terraform.tfvars # Default variable values
├── 📜 provider.tf # Provider configuration (AWS, Azure, GCP)
└── 📜 README.md # Documentation

📜 Organizing Terraform Files

🔹 main.tf (Infrastructure Definition)

This file contains the main Terraform configuration and resource definitions. Example:

provider "aws" {
region = var.region
}

resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
}

🔹 variables.tf (Input Variables)

Defines configurable parameters for Terraform resources.

variable "region" {
description = "AWS region to deploy resources"
type = string
}

variable "ami_id" {
description = "AMI ID for EC2 instance"
type = string
}

🔹 outputs.tf (Output Values)

Declares outputs to display useful information after Terraform applies the changes.

output "instance_public_ip" {
description = "Public IP of the EC2 instance"
value = aws_instance.web.public_ip
}

📦 Using Modules for Better Scalability

Modules help structure and reuse Terraform configurations. Below is an example module for an EC2 instance:

modules/compute/main.tf

resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
}

modules/compute/variables.tf

variable "ami_id" {}
variable "instance_type" {}

modules/compute/outputs.tf

output "public_ip" {
value = aws_instance.web.public_ip
}

Using the Module in main.tf

module "web_instance" {
source = "../modules/compute"
ami_id = "ami-123456"
instance_type = "t2.micro"
}

☁️ Remote State Storage (S3/Azure Blob)

Terraform state files should be stored remotely to enable collaboration and prevent state corruption.

🔹 AWS S3 Backend

terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "env/dev/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}

🔹 Azure Blob Storage Backend

terraform {
backend "azurerm" {
resource_group_name = "terraform-rg"
storage_account_name = "terraformstorage"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}

🎯 Best Practices

✅ Use modules to promote reusability.
✅ Store state files remotely (S3, Azure Blob).
✅ Implement environment-specific configurations (e.g., dev, prod).
✅ Use backend.tf to avoid storing sensitive information in the repo.
✅ Enable versioning and locking for remote state to prevent conflicts.


🔗 References

📌 Terraform Official Documentation
📌 Best Practices Guide

🚀 Happy Terraforming!