DEV Community

Cover image for Terraform File Structures
Brian Mengo
Brian Mengo

Posted on

Terraform File Structures

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;

  1. Terraform loads all .tf files in the current directory
  2. Files are loaded in lexicographical order (alphabetical)
  3. All .tf files are merged into a single configuration

Recommended 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
Enter fullscreen mode Exit fullscreen mode

Common recommended files in the root module include:

  1. main.tf: Contains primary resource definitions such as S3, VPC, EC2, etc. Alternatively, resources may be further subdivided into files named after the resource type (e.g., s3.tf, vpc.tf, ec2.tf), but this can become complex with many resources.
  2. variables.tf: Dedicated file for input variable declarations (moved out from main.tf).
  3. outputs.tf: File for output declarations.
  4. providers.tf: Contains provider configuration.
  5. backend.tf: Contains backend configuration for state management.
  6. terraform.tfvars: File for input variable values (sensitive values should not be committed).
  7. terraform.tfvars.example: Template file for variable values to be shared publicly without exposing secrets.
  8. .gitignore: To exclude sensitive or unnecessary files from being committed to version control.
  9. README: Documentation file. Key best practice: Do not commit .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

  • Multiple environments: Separate folders or configurations for 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
Enter fullscreen mode Exit fullscreen mode
  • Modularisation: Using modules for logically grouped resources, e.g., networking, compute, security modules.
modules/
├── vpc/
├── security/
└── compute/

Enter fullscreen mode Exit fullscreen mode

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:

  • Easier to maintain
  • Easier to scale
  • Easier for team to collaborate
  • Easier to troubleshoot

Below is the video that helped me understand this concept;

Top comments (0)