This project demonstrates how to deploy enterprise infrastructure using HCP Terraform Stacks across multiple teams, environments, and AWS regions with advanced orchestration, cost controls, and team isolation. HCP Terraform Stacks help you manage complex infrastructure deployments across multiple environments by providing a different model of infrastructure management from Terraform workspaces.
Instead of loosely coupled workspaces, a Stack consists of a set of components that are organized into one or more deployments, each of which HCP Terraform will provision as a unit. Each of the deployments in your Stack will provision the same Terraform configuration, defined by your Stack's components. A component is a Terraform module, which you can customize with input variables.
Stacks allow you to manage the lifecycle of each of your deployments independently, since changes to one deployment in your Stack do not affect the others. Each deployment in a Stack represents a set of infrastructure that works together, such as a dev, test, or production environment. HCP Terraform will roll out changes to each deployment at a time, and allows you to track changes across your environments.
Key benefits:
- Components: Terraform modules that can be customized with input variables
- Deployments: Independent instances representing different environments (dev, test, production)
- Lifecycle Management: Changes to one deployment don't affect others
- Rollout Control: Deploy changes to each environment individually
- Cross-Environment Tracking: Clear visibility of changes across all environments
graph TB
subgraph "Core Infrastructure Stack"
A[VPC & Networking]
B[Security Groups]
C[NAT Gateways]
end
subgraph "Shared Services Stack"
D[RDS Database]
E[Redis Cache]
F[CloudWatch Logs]
end
subgraph "Team Stacks"
G[Customer Team]
H[Payment Team]
I[Analytics Team]
end
A --> D
A --> G
A --> H
A --> I
D --> G
D --> H
D --> I
This Terraform Stack consists of multiple components organized into deployment configurations for enterprise-scale infrastructure:
terraform-stack-deploy/
├── LICENSE
├── README.md
├── deployments.tfdeploy.hcl # Multi-environment deployment configurations
├── components.tfcomponent.hcl # Stack component definitions
├── providers.tfcomponent.hcl # Provider configurations with OIDC auth
├── variables.tfcomponent.hcl # Stack-level variables and team configs
├── outputs.tfcomponent.hcl # Comprehensive stack outputs
└── stacks/ # Component source modules
├── core-infrastructure/ # VPC, subnets, security groups
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── shared-services/ # RDS, Redis, monitoring
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── application-team/ # Team-specific ECS applications
│ └── (team application modules)
└── java-app-module/ # Sample Java application module
└── (Java application infrastructure)
The repository includes Stack configuration files with the extension .tfcomponent.hcl and a deployments file named deployments.tfdeploy.hcl. These configuration files serve as the blueprint for the enterprise infrastructure your Stack will manage across multiple teams and environments.
This tutorial assumes that you are familiar with the Terraform and HCP Terraform workflows. If you are new to Terraform, complete the Get Started collection first. If you are new to HCP Terraform, complete the HCP Terraform Get Started tutorials first.
In order to complete this tutorial, you will need the following:
- AWS account with appropriate permissions
- HCP Terraform account with Stacks enabled for your organization
- HCP Terraform variable set configured with your AWS credentials
- Git repository connected to HCP Terraform workspace
HCP Terraform Stacks use specific file types to define your infrastructure:
components.tfcomponent.hcl- Defines the components in your Stackproviders.tfcomponent.hcl- Configures providers for your Stackvariables.tfcomponent.hcl- Defines input variables for your Stackoutputs.tfcomponent.hcl- Defines output values from your Stack
deployments.tfdeploy.hcl- Defines deployments and their specific configurations
A Terraform Stack is made up of one or more components, each sourced from a Terraform module and configured with inputs and the module's specified providers. HCP Terraform will provision all of these components for each of the deployments in your Stack. Each deployment block defined in .tfdeploy.hcl files represents an independent deployment of this Stack's infrastructure.
The providers.tfcomponent.hcl file contains provider configurations for your Stack:
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.7.0"
}
}
provider "aws" "configurations" {
for_each = var.aws_regions
config {
region = each.value
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
default_tags {
tags = var.common_tags
}
}
}The required_providers block defines the providers used in this configuration, and uses a syntax similar to the required_providers block nested inside the terraform block in Terraform configuration.
The provider configuration includes:
- Multiple provider configurations: Using
for_eachto configure providers for multiple regions - OIDC authentication: Using
assume_role_with_web_identityfor secure authentication - Provider labels: The
"configurations"label allows multiple configurations of the same provider type
The assume_role_with_web_identity block configures provider authentication to use a JWT identity token managed by trust relationship. Each of your deployments will pass the ARN of your trust relationship's IAM role and a corresponding JWT identity token generated by AWS each time you plan or apply your Stack.
Components are defined in components.tfcomponent.hcl. This Stack includes enterprise-scale components:
component "core_infrastructure" {
source = "./stacks/core-infrastructure"
inputs = {
environment = var.environment
aws_region = var.aws_region
vpc_cidr = var.vpc_cidr
availability_zones = var.availability_zones
tags = var.common_tags
}
providers = {
aws = provider.aws.main
}
}
component "shared_services" {
source = "./stacks/shared-services"
inputs = {
environment = var.environment
aws_region = var.aws_region
vpc_id = component.core_infrastructure.vpc_id
private_subnet_ids = component.core_infrastructure.private_subnet_ids
application_cidrs = component.core_infrastructure.application_cidrs
db_password = var.db_password
redis_auth_token = var.redis_auth_token
tags = var.common_tags
}
providers = {
aws = provider.aws.main
}
depends_on = [component.core_infrastructure]
}
component "customer_team" {
source = "./stacks/application-team"
inputs = {
team_name = "customer-team"
environment = var.environment
aws_region = var.aws_region
# Network dependencies from core infrastructure
vpc_id = component.core_infrastructure.vpc_id
private_subnet_ids = component.core_infrastructure.private_subnet_ids
# Shared services dependencies
database_endpoint_ssm_path = component.shared_services.ssm_database_endpoint_path
redis_endpoint_ssm_path = component.shared_services.ssm_redis_endpoint_path
# Team-specific configuration
applications = var.customer_team_applications
budget_amount = var.customer_team_budget
tags = var.common_tags
}
providers = {
aws = provider.aws.main
}
depends_on = [component.shared_services]
}A Stack component includes a Terraform module as a source, input arguments for the module, and the providers that Terraform will use to provision your infrastructure. Each component can also include output values, and components can refer to the output values from other components.
Notice the component dependencies:
shared_servicesdepends oncore_infrastructurefor VPC and networkingcustomer_team(and other teams) depend onshared_servicesfor database and cache endpoints- This creates a deployment order: core infrastructure → shared services → application teams
Each deployment represents an instance of all of the components in your Stack, which you customize with the inputs argument. You can use multiple deployments to manage self-contained instances of your Stack's infrastructure, such as development, test, and production environments.
Deployments are defined in deployments.tfdeploy.hcl:
# Identity token for AWS authentication using OIDC
identity_token "aws" {
audience = ["aws.workload.identity"]
}
deployment "development" {
inputs = {
aws_regions = ["us-east-1"]
role_arn = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
identity_token = identity_token.aws.jwt
common_tags = {
stacks-preview-example = "lambda-component-expansion-stack"
Project = "scaling-terraform-stacks"
Environment = "dev"
}
environment = "dev"
aws_region = "us-east-1"
vpc_cidr = "10.0.0.0/16"
# Team configurations
customer_team_applications = {
customer_service = {
app_name = "customer-service"
# ... additional configuration
}
}
# ... additional team configurations
}
}
deployment "production" {
inputs = {
aws_regions = ["us-east-1", "us-west-1"]
role_arn = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
identity_token = identity_token.aws.jwt
common_tags = {
stacks-preview-example = "lambda-component-expansion-stack"
Project = "scaling-terraform-stacks"
Environment = "production"
}
environment = "production"
aws_region = "us-east-1"
vpc_cidr = "10.1.0.0/16"
# ... production-specific configuration
}
}Each deployment includes:
- Independent environment: Self-contained instance of your infrastructure
- Custom inputs: Environment-specific configuration values
- Regional deployment: Can span multiple AWS regions
- Team configurations: Isolated resources for different teams
- OIDC authentication: Secure authentication using identity tokens
Now that you have configured your Stack with the ARN of your AWS role, create and deploy your Stack.
-
Log in to HCP Terraform and select the organization you wish to use for this tutorial.
-
Enable Stacks for your organization by navigating to Settings > General. Ensure that the box next to Stacks is checked, and click the Update organization button.
-
Create a new project by navigating to Projects, click the + New Project button, name your project (e.g., "Terraform Stacks Demo"), and click the Create button.
-
Configure Variable Set for your project. Navigate to your organization's Settings > Variable sets page, and select your AWS credentials variable set. Under Variable set scope, select "Apply to specific projects and workspaces", and add your project to the list. Click the Save variable set button.
Your Stack uses a JWT identity token to authenticate the AWS provider. You must first establish an OIDC trust relationship between your AWS account and HCP Terraform, and create an AWS role with the appropriate permissions.
- Fork the identity token repository from the HashiCorp tutorial template
- Create a workspace in your project to provision identity tokens
- Configure the workspace with your organization and project details
- Apply the configuration to create your OpenID provider, policy, and role
- Copy the role_arn output value for use in your deployments
-
In HCP Terraform, navigate to your project and select New > Stack.
-
Connect to version control by selecting your GitHub account and choosing your repository.
-
Configure the Stack by leaving the Stack name the same as your repository name, and click Create Stack.
-
HCP Terraform will load your Stack configuration from your VCS repository.
Once HCP Terraform loads your configuration, it plans your changes. HCP Terraform plans each deployment separately, and you can choose when to apply each plan.
-
Review deployments under "Deployments rollout" - HCP Terraform lists your development and production deployments with their current status.
-
Deploy development environment:
- Select your development deployment to review the plan
- Click "Approve plan" to apply the changes
- Monitor the deployment progress
-
Deploy production environment:
- Navigate to your production deployment
- Review and apply the plan
- Once complete, your Stack's status will change to "Rolled out"
You can add new deployments by updating your deployments.tfdeploy.hcl file:
deployment "test" {
inputs = {
aws_regions = ["us-east-1", "us-west-1"]
role_arn = "arn:aws:iam::YOUR_ACCOUNT:role/YOUR_ROLE_NAME"
identity_token = identity_token.aws.jwt
common_tags = {
Environment = "test"
Project = "scaling-terraform-stacks"
}
environment = "test"
# ... test-specific configuration
}
}Commit and push this change to your repository, and HCP Terraform will automatically add the new deployment to your Stack.
# Validate configuration
tfstacks validate
# Plan deployment
tfstacks plan \
-organization="ScalingDemo" \
-stack="st-<STACK-ID>" \
-deployment="development"
# Apply through HCP Terraform UI
# (HCP Terraform automatically triggers plan on git push)# Validate and plan
tfstacks validate
tfstacks plan \
-organization="ScalingDemo" \
-stack="st-<STACK-ID>" \
-deployment="staging"
# Apply with manual approval in HCP Terraform
# (Requires approval in HCP Terraform UI)# Validate and plan with strict controls
tfstacks validate
tfstacks plan \
-organization="ScalingDemo" \
-stack="st-<STACK-ID>" \
-deployment="Production"
# Apply with senior approval in HCP Terraform
# (Requires multiple approvals in HCP Terraform UI)Before finishing this tutorial, destroy your infrastructure:
- Navigate to your Stack's Deployments page, and select each deployment
- Navigate to the Destruction and Deletion page and click "Create destroy plan"
- Approve the destroy plan to remove your resources
- Remove your Stack by navigating to your Stack's Destruction and Deletion page and clicking "Force delete Stack"
- Clean up identity token infrastructure by destroying your identity token workspace
This project demonstrates how to:
- Deploy enterprise infrastructure using HCP Terraform Stacks across multiple environments
- Manage component dependencies between core infrastructure, shared services, and application teams
- Use OIDC authentication for secure AWS provider authentication
- Organize deployments for development, staging, and production environments
- Scale infrastructure with team-specific configurations and budgets
- Track changes across multiple environments independently
- Implement team isolation with separate ECS applications and resource boundaries
- Manage shared services like RDS databases and Redis cache across teams
- Apply enterprise governance with cost controls and approval workflows