This workshop assumes you’re already familiar with the techniques and concepts in the Introduction & Key Concepts section. If you haven’t reviewed it yet, start with AWS Architecture and work your way through the rest of the section to fully understand the mechanics and philosophy behind our setup.
Prerequisites
- AWS SSO signed in:
aws sso login --profile <your-profile>. See Getting Started with AWS SSO if you need help setting this up
- Fast Foundation infrastructure repository cloned
- You know the target account / environment / region you’ll deploy to
- You have a VPC and at least one subnet ready (private subnet recommended)
Target folder (where to place your unit)
If your ec2 folder did not exist, add an empty ”…/ec2/_service.hcl” file with contentlocals{
service = basename(get_terragrunt_dir())
}
Pick the account, environment, and region. Example path for a dev workload:
fast-foundation-infrastructure/
└── Workloads/
└── Development/
└── <development_workload_account>/
└── development
└── <your_region>/
└── ec2/
└── service.hcl
└── web-ec2/
├── terragrunt.hcl
└── inputs.hcl
If inputs.hcl isn’t there, your before-hooks will generate/sync it on terragrunt init.
Step 1 — Create terragrunt.hcl
This references the official module from the Terraform Registry and wires in Fast Foundation’s parameter sync.
terraform {
# Use the official module directly (no wrapper)
source = "tfr://registry.terraform.io/terraform-aws-modules/ec2-instance/aws?version=5.8.0"
# Parameter management (before-hooks) — already present in your repo scripts
before_hook "secrets_management" {
commands = ["init", "plan", "apply"]
execute = [
"${local.parameter_script}",
"${local.local_file_path}",
"${include.root.locals.project_name}-terragrunt-states",
"${local.s3_key}",
"${local.aws_profile_infrastructure}"
]
run_on_error = false
}
}
include "root" {
path = find_in_parent_folders("root.hcl")
expose = true
}
locals {
# Shared Configurations
region_vars = include.root.locals.region_vars.locals
service_vars = include.root.locals.service_vars.locals
# Unit Inputs from inputs.hcl
inputs = try(read_terragrunt_config("${get_terragrunt_dir()}/inputs.hcl").locals,{})
# Parameter management
s3_key = "${path_relative_to_include("root")}/inputs.hcl"
local_file_path = "${get_terragrunt_dir()}/inputs.hcl"
aws_profile_infrastructure = "${include.root.locals.project_name}-infrastructure"
project_name = include.root.locals.project_name
# Cross-platform script selection
script_base_path = "${dirname(find_in_parent_folders("root.hcl"))}/_scripts/parameter-management"
script_preference = get_env("TG_SCRIPT_TYPE", "auto")
parameter_script = (
local.script_preference == "powershell" ? "${local.script_base_path}.ps1" :
local.script_preference == "python" ? "${local.script_base_path}.py" :
local.script_preference == "bash" ? "${local.script_base_path}.sh" :
"${local.script_base_path}.sh" # Default fallback to bash
)
# Use folder name for a friendly resource name
instance_name = basename(get_terragrunt_dir())
}
inputs = {
# Minimal set for the module to launch an instance
name = basename(get_terragrunt_dir()) #Naming best practice
instance_type = try(local.inputs.instance_type, "t3.micro")
monitoring = try(local.inputs.monitoring, false)
# key_name = try(local.inputs.key_name, "my-keypair")
# Reference VPC from parameter store
vpc_security_group_ids = [try(local.inputs.security_group_id, "sg-1234567890abcdef")]
subnet_id = try(local.inputs.subnet_id, "subnet-1234567890abcdef")
region = try(local.region_vars.region, "us-west-2")
tags = {
Environment = try(local.environment_vars.environment, "development")
Name = basename(get_terragrunt_dir())
Instance = local.instance_name
DeployedBy = "terragrunt"
}
}
Parameter values are stored here and synced to S3. Example for development:
locals {
instance_type = "t3.micro"
subnet_id = "subnet-1234567890abcdef" # Replace with a valid subnet ID
security_group_id = "sg-1234567890abcdef" # Replace with a valid security group ID
monitoring = false
}
Step 3 — Deploy the instance
Run these commands from your new folder:
terragrunt init
terragrunt plan
terragrunt apply
The before-hooks will sync inputs.hcl and ensure your AWS SSO session is valid.
What you learned
- How to use the official EC2 module directly with Terragrunt
- How before-hooks protect you against drift and missing inputs
- How to keep parameters in sync via S3
Cleanup
Important: Don’t forget to clean up the resources you created during this workshop to avoid unnecessary AWS charges.
To destroy the EC2 instance and all associated resources, run the following command from your deployment folder:
When prompted, type yes to confirm the destruction of resources.