Data report"State of code review 2024" is now liveRead the full report

Best practices for Terraform project structures

Kenny DuMez
Kenny DuMez
Graphite software engineer

Terraform by HashiCorp is a popular infrastructure as code (IaC) tool used to provision and manage resources and infrastructure in any cloud. Organizing Terraform code effectively can significantly improve the maintainability and scalability of your infrastructure projects. This guide outlines several Terraform project structures, providing detailed examples and explaining how each approach can be beneficial depending on your project’s needs.

A basic Terraform project structure might look something like this:

Terminal
terraform-project/
├── main.tf # Main Terraform configuration file
├── variables.tf # Variable definitions
├── outputs.tf # Output values
└── terraform.tfvars # Values for the declared variables

Explanation:

  • main.tf: This file contains the primary configuration details, such as provider configuration and resource declarations.
  • variables.tf: This file declares variables to be used within your Terraform configuration, enhancing modularity and reusability.
  • outputs.tf: Outputs useful data about your resources, which can be used for referencing in other Terraform projects or for external use.
  • terraform.tfvars: Typically contains values for the variables defined in variables.tf, allowing for customization per environment without altering the main configuration.

For larger projects, a module-based structure is recommended. It might look like this:

Terminal
terraform-project/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── modules/
├── network/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── compute/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── database/
├── main.tf
├── variables.tf
└── outputs.tf
  • modules/: This directory contains subdirectories for each module (e.g., network, compute, database), which encapsulate specific components of the infrastructure.
    • network/: Contains Terraform files managing networking resources like VPCs, subnets, and NAT gateways.
    • compute/: Manages compute resources such as EC2 instances or Kubernetes clusters.
    • database/: Manages database components, for example, RDS instances or DynamoDB tables.
  • By using modules, you can reuse code across different projects and keep your Terraform code DRY (Don't Repeat Yourself).

When you need to manage multiple environments (like development, staging, and production), an environment-specific structure can be used:

Terminal
terraform-project/
├── global/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── environments/
├── development/
│ ├── main.tf
│ ├── terraform.tfvars
│ └── outputs.tf
├── staging/
│ ├── main.tf
│ ├── terraform.tfvars
│ └── outputs.tf
└── production/
├── main.tf
├── terraform.tfvars
└── outputs.tf
  • global/: Contains Terraform configurations that are common across all environments, such as IAM roles or S3 buckets.
  • environments/: Each subdirectory represents a specific environment with its own configurations that override or extend the global settings.
    • This structure allows for clear separation of environments, minimizing the risk of changes in one environment affecting another.

Terraform workspaces allow you to manage state files separately for the same configuration, making it easier to manage different environments with minimal duplication of code:

Terminal
terraform-project/
├── main.tf
├── variables.tf
├── outputs.tf
└── environments.tfvars
├── development.tfvars
├── staging.tfvars
└── production.tfvars
  • environments.tfvars/: Contains variable files for each workspace (environment). You switch between workspaces using terraform workspace select development, for example.
  • This setup uses the same set of Terraform files for each environment, differing only in the variable values provided by the tfvars files corresponding to each workspace.

Choosing the right project structure for your Terraform code depends largely on the size of your infrastructure, the complexity of the environments, and how distinct the configurations are across these environments. Each structure offers different benefits, such as modularity, reusability, and separation of concerns, which can help streamline operations and reduce errors as your infrastructure scales.

For more information on Terraform project structure, see the official Terraform docs.

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2