New to Terragrunt? We recommend starting with the official Terragrunt quick start to learn the basics before diving into Fast Foundation’s implementation.
💡 Pro Tip: Always run
terragrunt plan before apply to review changes.Overview
Fast Foundation uses Terragrunt as the orchestration layer for Terraform. Terragrunt provides configuration management, dependency handling, and integrates our secrets management system that keeps infrastructure secrets consistent across environments.Why Terraform + Terragrunt?
Terraform defines what to create (resource definitions).Terragrunt defines how to orchestrate it (configuration, dependencies, consistency checks).
Benefits in Fast Foundation
Benefits in Fast Foundation
- DRY principles – Avoid repeating configuration across environments
- Dependency management – Clear ordering of infrastructure components
- Remote state – Centralized state using S3 (Simple Storage Service) and DynamoDB locks
- Environment promotion – Move configurations cleanly between dev/staging/prod
- Custom secrets management – Our system keeps secrets secure in SSM Parameter Store
Repository Structure
Infrastructure repository layout
For details about Organizational Units (OUs) and accounts, see the AWS Architecture section.
As a rule of thumb: OUs start with Capital letters, while accounts use lowercase.
- shared config files, like
_account.hcl,_environment.hcl,_region.hcl,_service.hcl, to set account, environment, region or service level configurations. - resource types or groups folders (e.g.,
ec2,clusters (eks/ecs),lambda, etc.) - each resource unit contains a Terragrunt file (the “unit”) and an inputs file (the parameters).
Shared Config Files
Fast Foundation relies on shared configuration files at different levels of the hierarchy. These files let you define variables once and automatically inherit them in all child units.root.hcl– global project-wide configuration (backend, provider setup, hooks)_account.hcl– account-specific settings like account IDs, tags, IAM roles_environment.hcl– environment-wide values like environment name, prefixes, or SSO roles_region.hcl– region-specific settings such as availability zones or region tags_service.hcl– service-specific settings such as a common security group rule for all ec2 instances
terragrunt.hcl using include blocks, which makes shared variables directly available in your local unit without redefining them.
The
root.hcl already imports shared configuration variables. Including root is enough to access variables in _account.hcl, _environment.hcl,_region.hcl and _service.hcl files.You can easily access variables with include.root.account_vars, include.root.environment_vars, include.root.region_vars,include.root.service_vars, inside your unit configuration.What lives where?
terragrunt.hcl– The “unit” file. It invokes a Terraform module, wires dependencies, configures remote state, and registers hooks.inputs.hcl– The parameters for that unit (names, ARNs, sizes, tags, etc.). These inputs should not contain hardcoded sensitive information since they are commited to Git. For sensitive data make reference to secrets stored in SSM Parameter Store.
Secrets management – How sensitive information stays secure and consistent
All the secret parameters used in the units are not stored locally or pushed to any repository. Instead, Fast Fundation stores all of them in SSM Parameter Store as JSON, and provides an automated secrets management layer that replaces secrets references in theinputs.hcl file with the actual values stored in AWS.
This is what the Secrets Management Automation does for you:
- On
init: Automatically creates the secret parameter in SSM Parameter Store if it does not already exist (it is created as an empty JSON object). - On
plan&apply: Replaces the references to the secrets in theinputs.hclfile with the actual secret values stored in SSM Parameter Store.
Secrets Management
Before-Hooks
In Fast Foundation, before-hooks are already part of the standard Terragrunt setup. You only need to add them if you’re creating a brand-new unit from scratch.
init, plan, apply) to enforce prerequisites and prevent mistakes.
Why they matter
- ✅ Ensure AWS SSO sessions are valid before you run anything
- ✅ Make use of secrets stored in SSM Parameter Store when running a
planorapply - ✅ Run validations (formatting, required files present, etc.) automatically
What to add to your Unit if it contains sensitive inputs
If you are creating a new unit, and that unit has sensitive inputs that you don’t want to commit into Git, you will need to add some blocks to itsterragrunt.hcl file.The secrets-management scripts are already included in your repository. You need to add the
before_hook and after_hook sections, and the locals parameters described below to your terragrunt.hcl:
enable_ssm_parameter flag into your inputs.hcl file, and make reference to the secret parameters appending the prefix ssm:// to the name of the key to reference in the secret stored in SSM Parameter Store:
Behavior
Once the necessary changes are made to theterragrunt.hcl file and the enable_ssm_parameter flag is set to true in the inputs.hcl file, run terragrunt init.
This will create (if it does not already exist) a parameter in SSM Parameter Store. This parameter is stored in the same AWS Account that the Unit is included into, and its name will be the path to the Unit.
For example, if the parameter is created for the OpenSearch cluster located in Security/Production/log-archive-production/production/us-east-1/logging/opensearch/fast-foundation-logging, the parameter will live
in the log-archive-production account with the name Security/Production/log-archive-production/production/us-east-1/logging/opensearch/fast-foundation-logging.
The parameter is created as an empty JSON object. You will have to manually access the parameter and populate it with your sensitive information as key-value pairs:
plan or apply, the secrets management script will replace the references made to the secret keys in the inputs.hcl file with the actual secret values. It will create a temporary
inputs.resolved.hcl file for this purpose that is automatically deleted once the command has finished running.
Best Practices
Use unit folder names consistently
If possible, use the folder name as the resource name. This keeps the repository intuitive: the folder you are working in directly reflects the deployed resource.ec2/my_app_server/→ contains inputs/terragrunt formy_app_serverEC2 instanceeks/my_cluster/→ contains inputs/terragrunt for yourmy_clusterEKS cluster
Secrets Management
Avoid these practices — they can compromise your infrastructure:
- Hardcoding values in Terraform files
- Reusing production secrets in development
Gotchas
Mock outputs
Mock outputs let
terragrunt init and terragrunt plan run even when the dependency hasn’t been created yet. They’re placeholders — not the real values.
For additional information, visit the official Terragrunt documentation- ✅ Plans succeed early because placeholders exist
- ⚠️ Applies may fail later if the real resource doesn’t exist yet
Key things to remember
- If something works on plan but fails on apply with errors like “resource doesn’t exist”, it probably used mock outputs during planning
- Always check whether dependencies (like VPCs, subnets, IAM roles) are actually applied before trusting a green
terragrunt plan
State lock issues
Terragrunt and Terraform use DynamoDB locks to prevent multiple people from applying changes at the same time on the same unit. If you see a state lock error, it usually means someone else is already running a deployment. What to do:- ⏳ Wait for the other deployment to finish.
- ✅ Verify you’re not overwriting someone else’s changes.
- 🚀 Apply your changes once you’re sure everything is okay.