What you’ll build
- A parent Terraform configuration that calls local modules.
- Three local modules:
vpc,subnet, andec2. - Data flow that passes outputs from one module into another (e.g., VPC ID -> Subnet -> EC2).
Directory and file layout
Create a top-level Terraform directory (this is the parent module). Inside it add common files and amodules subdirectory with three child modules.
Below are cleaned-up module implementations and the parent configuration examples. Keep these modules focused and parameterized so they are reusable across accounts and environments.
VPC module
This module creates a VPC and exposes its ID as an output. modules/vpc/main.tfSubnet module
This module provisions a subnet and the supporting network resources: an Internet Gateway, a route table, and a route table association. It accepts avpc_id input and returns the subnet_id.
modules/subnet/main.tf

EC2 module
This module creates a security group and an EC2 instance. Inputs include VPC and subnet IDs plus AMI, instance type, and an instance name. Outputs include the instance ID and public IP. modules/ec2/main.tfParent configuration
The parent module declares the AWS provider and calls the child modules. Note how we wire outputs into module inputs. providers.tf (parent)Tooling and basic workflow
After you add or change modules, follow this basic workflow.- Initialize the working directory (downloads providers and registers modules)
- Format your files
- Create and review a plan, then apply

Notes and best practices
Use module outputs to pass information between modules (for example:
module.vpc.vpc_id -> module.subnet_module.vpc_id). Keep modules small, well-documented, and parameterized so they can be reused across environments.Running
terraform apply will create resources in your cloud account and may incur charges. Always review the plan before applying and destroy resources when they are no longer needed.- Use descriptive variable names and include
descriptionin eachvariables.tf. - Prefer explicit module inputs over relying on implicit defaults in a parent configuration.
- You can call a module multiple times with different arguments, or use
for_eachto create multiple instances of a module. - Split responsibilities logically (networking, compute, database) to simplify testing and reuse.
- Consider versioning modules if you extract them to a shared registry.
Summary
- You created a local module structure (
vpc,subnet,ec2), implemented resources along with variables and outputs, and wired module outputs into parent module inputs. - This modular approach reduces duplication and makes it easy to create multiple similar environments by calling the same module with different inputs.