Hen Itzhaki
DevOps Engineer
Terragrunt(Terraform) Folder Structure - Best Practices for Organizing Your Infrastructure
When managing infrastructure as code with Terraform and Terragrunt, having a well-organized folder structure is crucial. Poor structuring can lead to complexity, hard-to-maintain configurations, and inefficiencies in team collaboration. Following best practices can improve scalability, manageability, and reusability.
What You'll Learn
- The KISS principle (Keep It Simple, Stupid)
- The DRY principle (Don't Repeat Yourself)
- A recommended folder structure for Terragrunt
- Configuration files & hierarchy
- Real-world examples of structuring Terragrunt projects
Keep It Simple, Stupid (KISS)
One of the most important principles in software engineering is KISS – keeping things simple reduces complexity and improves maintainability.
When organizing your Terragrunt folders, follow these rules:
- Structure by environments first: Separate configurations for dev, staging, and production.
- Use a consistent naming convention: Keep directories structured similarly across providers.
- Minimize redundant configurations: Use HCL files to apply settings globally.
- Leverage inheritance: Place shared configurations in higher-level folders.
Avoid Repetition with the DRY Principle
The Don't Repeat Yourself (DRY) principle ensures that configurations are reusable and maintainable. Applying DRY in Terragrunt means:
- Using
includeblocks to inherit settings from parent configurations. - Storing global variables in
root.hcland referencing them in child modules. - Defining reusable modules for commonly deployed infrastructure (VPCs, IAM policies, storage).
- Using parameterized inputs in
terragrunt.hclinstead of hardcoding values.
Structuring for Big-to-Small Impact
Big Changes
Example: Running Terragrunt at live/dev/, live/staging/, or live/production/
Impact: Affects all sub-resources in that environment across every provider (AWS, GCP, on-prem).
Medium Changes
Example: Running Terragrunt in a specific provider folder, like live/dev/aws/, live/dev/gcp/, or live/production/
Impact: Affects all resources for that one datacenter within the specified environment.
Small Changes
Example: Running Terragruntin a region, account, or service subfolder*, e.g., at live/dev/, live/staging/, or live/dev/aws/us-west-2/account/networking/
Impact: Affects only the localized components in that region or account/service directory.
This ensures that large changes are managed efficiently while smaller ones remain localized.
Recommended Terragrunt Folder Structure
Here's a scalable and flexible structure widely used in Terragrunt projects:
Why This Structure?
- Scalability: Easily expand infrastructure without restructuring.
- Flexibility: Accommodates multiple cloud providers and hybrid setups.
- Reusability: Reduces duplication through shared configurations.
Key Configuration Files Explained
Sets global configurations used across all environments:
Defines environment-specific settings (dev, staging, production, etc.):
Manages cloud-provider-specific settings (AWS, GCP, etc.):
Specifies region-specific variables:
Real-World Example : VPC Setup
In this example, we're provisioning a VPC using the terraform-aws-modules/vpc/aws module.
The VPC name is dynamically generated using the environment name (e.g., dev) and the current service directory name (e.g., vpc), resulting in a name like dev-vpc.
Modularizing Infrastructure with Reusable Modules
In the spirit of DRY, creating reusable modules for networking, EKS clusters, or any other commonly deployed infrastructure is highly recommended. This way, teams only need to define variables specific to their use case rather than duplicating large configuration blocks.
Enforcing Ownership with CODEOWNERS
To streamline change control, define a CODEOWNERS file in your repository.
This helps ensure that only the correct teams or individuals can approve changes to certain directories.
Conclusion
A well-structured Terragrunt project ensures scalability, maintainability, and clarity. By applying KISS & DRY principles, you can streamline infrastructure management.
- DRY ensures reusability and reduces duplication.
- Hierarchical inheritance keeps configurations clean.
- Modular infrastructure allows for efficient team-based workflows.
- Layered changes (big → medium → small) keep deployments structured.