
Brian MengoIntroduction Today we focus on file structure and organising Terraform projects. Initially all...
Introduction
Today we focus on file structure and organising Terraform projects. Initially all resources were placed in a single main.tf file to simplify the learning process. What we are doing now is to improve the project structure by splitting resources and configurations into multiple files for better readability, collaboration and maintainablity.
The root directory of a Terraform project is called the root module.
Terraform File Loading
There is no strict mandatory naming convention for Terraform files.recommendations come from HashiCorp best practices but are flexible.
How Terraform loads files;
.tf files in the current directory.tf files are merged into a single configurationRecommended File Structure and Best Practices
project-root/
├── backend.tf # Backend configuration
├── provider.tf # Provider configurations
├── variables.tf # Input variable definitions
├── locals.tf # Local value definitions
├── main.tf # Main resource definitions
├── vpc.tf # VPC-related resources
├── security.tf # Security groups, NACLs
├── compute.tf # EC2, Auto Scaling, etc.
├── storage.tf # S3, EBS, EFS resources
├── database.tf # RDS, DynamoDB resources
├── outputs.tf # Output definitions
├── terraform.tfvars # Variable values
└── README.md # Documentation
Common recommended files in the root module include:
s3.tf, vpc.tf, ec2.tf), but this can become complex with many resources..tfvars files containing secrets or sensitive values to GitHub; instead, commit a .example template..gitignore Configuration and Files to Exclude
The .gitignore file should exclude:
.terraform/ directory (Terraform metadata, plugins, and cache)*.tfstate and *.tfstate.backup files (Terraform state files).terraform.lock.hcl (provider dependency lock file)*.log files (e.g., crash logs)terraform.tfvars and any *.tfvars.json files (to avoid publishing sensitive data)
These exclusions protect sensitive information and prevent unnecessary files from cluttering the repository.
Advanced Project Structures and Environment Management
dev, staging, prod, each with distinct main.tf files.
environments/
├── dev/
│ ├── backend.tf
│ ├── terraform.tfvars
│ └── main.tf
├── staging/
│ ├── backend.tf
│ ├── terraform.tfvars
│ └── main.tf
└── production/
├── backend.tf
├── terraform.tfvars
└── main.tf
modules/
├── vpc/
├── security/
└── compute/
Another approach is to use the same Terraform configuration files for all environments but supply different terraform.tfvars files for each environment to inject environment-specific values.
Terraform should be readable first, functional second.
Day 6 helped me understand something deeper:
Good Terraform isn’t just about writing code—it’s about organizing it.
A clean structure makes your infrastructure:
Below is the video that helped me understand this concept;