Terraform
Terraform Stacks Concepts in HCP Terraform
HCP Terraform Stacks helps you to organize and reuse infrastructure definitions consistently across different environments. A Stack consists of two constructs:
- Modularized configuration called components
- Named instances of the group of components, customized with input values, called deployments

In this tutorial, you will configure, provision, and modify virtual infrastructure as you learn to do the following:
- Create a new Stack
- Deploy a Stack using HCP Terraform
- Add deployments to a Stack
- Add components to a Stack
Prerequisites
- An HCP Terraform account
- The Terraform CLI (v1.13.0+) installed locally
- A GitHub account
Preview Stacks concepts
Unlike the traditional Terraform root module structure, Stacks organizes infrastructure by components and deployments.
Components define the Terraform modules that make up your Stack's infrastructure.
Each deployment in a Stack defines an environment, such as a development or production environment. Each deployment configures the components to suit that environment.

The diagram shows the Stack you will configure in this tutorial. You will create your Stack with a single manifest component deployed to a single dev environment. Next, you will add test and prod deployments to your Stack. Then you will add a new component and apply it to all deployments.
Create example repository
Navigate to the template repository for this tutorial. Click the Use this template button and select Create a new repository. Choose a GitHub account to create the repository in and name the new repository learn-terraform-stacks-concepts. Leave the rest of the settings at their default values.
In your terminal, clone your example repository, replacing USER with your own GitHub username.
$ git clone https://github.com/USER/learn-terraform-stacks-concepts
Change to the repository directory.
$ cd learn-terraform-stacks-concepts
The repository directory contains the Terraform modules you will use to create your Stack's components, a .terraform-version file, numbered directories containing the final configuration for each step, and a .gitignore file. The .terraform-version file configures HCP Terraform to use the specified Terraform version to manage your Stack's infrastructure. HCP Terraform requires .terraform-version to run.
Create Stack configuration
Create and open a new file named components.tfcomponent.hcl in your editor. Then, paste the following configuration into the file to define the first component in your Stack.
components.tfcomponent.hcl
required_providers {
time = {
source = "hashicorp/time"
version = "~> 0.13.1"
}
}
provider "time" "this" {}
component "manifest" {
source = "./modules/manifest-module"
inputs = {
parent_directory = var.parent_directory
environment_name = var.environment_name
}
providers = {
time = provider.time.this
}
}
A Stacks component block uses a Terraform module as a source, sets any variable values for the module in the inputs argument, and specifies the providers Terraform will use to provision your infrastructure in the providers argument.
In this example, the component uses a local module that creates a timestamped manifest for the environment. The module inputs are set by two variables which you will create in the next step, parent_directory and environment_name.
Next, create and open a new file named variables.tfcomponent.hcl. Then, paste the following configuration into the file to define the variables you used in components.tfcomponent.hcl.
variables.tfcomponent.hcl
variable "parent_directory" {
description = "Parent directory environment directories are placed within"
type = string
default = "stacks_tutorial"
}
variable "environment_name" {
description = "Environment to deploy"
type = string
default = "DEFAULT_TARGET"
}
Each deployment in your Stack can customize the behavior of your components by setting values for these variables. Just as with Terraform modules, variables without a default value are required. For more information on variables, refer to Use input variables to add module arguments.
Create and open a new file named outputs.tfcomponent.hcl. Then, paste the following configuration into the file to define the outputs from your Stack.
outputs.tfcomponent.hcl
output "manifest_filename" {
description = "Manifest filename"
value = component.manifest.manifest_filename
type = string
}
output "manifest_contents" {
description = "Contents of manifest file"
value = component.manifest.manifest_contents
type = string
}
output "simulated_filesystem" {
description = "What the filesystem would look like"
value = concat([component.manifest.manifest_filename])
type = list(string)
}
Your Stack will output these values after applying the configuration. Practitioners deploying the Stack can use the output values, or pass them to other Stacks configurations or automation tools.
The three .tfcomponent.hcl files define the components, associated variables, and outputs that HCP Terraform manages for each of your stack's deployments.
Next, create and open a new file named deployments.tfdeploy.hcl. Paste the following configuration into the file to define your dev deployment.
deployments.tfdeploy.hcl
deployment "dev" {
inputs = {
environment_name = "dev"
}
}
Every deployment is made up of all the components specified in your Stack. Define a deployment with the deployment block in a file ending with .tfdeploy.hcl, customized with the inputs argument.
This deployment file specifies one deployment, which is customized with environment_name = "dev". Because parent_directory is not set in the inputs argument, HCP Terraform will use the default variable value for parent_directory defined in variables.tfcomponent.hcl.
In your terminal, initialize your Stack configuration.
$ terraform stacks init
Provider "hashicorp/time" is new and will be locked.
Downloading "hashicorp/time"@"0.13.1"....
Success! Configuration has been initialized and more commands can now be executed.
Terraform downloads the providers required by your Stack and creates a .terraform.lock.hcl file.
Format and validate your Stack configuration.
$ terraform stacks fmt
$ terraform stacks validate
.
Success! Terraform Stacks configuration is valid and ready for use within HCP Terraform.
Once you have created a valid Stack configuration, commit and push the configuration to your GitHub repository:
$ git add components.tfcomponent.hcl variables.tfcomponent.hcl deployments.tfdeploy.hcl outputs.tfcomponent.hcl .terraform.lock.hcl
$ git commit -m "Create initial Stack configuration"
$ git push
If you got stuck at any point during this step, refer to the 02-basic-configuration directory in the repository to see the code implemented for this step.
Create and deploy Stack in HCP Terraform
Navigate to HCP Terraform and select the organization you wish to use for this tutorial.
Next, ensure that Stacks is enabled for your organization by navigating to Settings > General. Ensure that the box next to Stacks is checked, and click the Update organization button.
Then navigate to Projects, click the + New Project button, name your project Learn Stacks, and click the Create button to create it.
Now, complete the following steps to create your Stack within your project:
- Click the Create a stack link.
- Select Version control workflow, then click Next.
- Choose your GitHub account from the list.
- Select the repository containing the example Stack for this tutorial,
learn-terraform-stacks-conceptsand click Next. - Click Create Stack to finish creating your Stack.
HCP Terraform loads your Stack configuration from your VCS repository. This process may take a few moments to complete.
Once HCP Terraform loads your configuration, it plans your changes.
Click on dev in the Deployment name column to review the changes to be applied. Then, click the Approve plan button to apply it now.
Expand the Outputs details. HCP Terraform lists the outputs produced by your Stack. The timestamp in manifest_contents is a static value that will stay the same across subsequent changes to the dev deployment.

Add new deployments
Now, you will add two new deployments to your Stack.
Open the deployments.tfdeploy.hcl file in your editor and add two new deployment blocks:
deployments.tfdeploy.hcl
deployment "test" {
inputs = {
environment_name = "test"
}
}
deployment "prod" {
inputs = {
environment_name = "prod"
}
}
Commit and push this change to your GitHub repository:
$ git add deployments.tfdeploy.hcl
$ git commit -m "Add test and prod deployments"
$ git push
Navigate to your Stack's Configurations page. HCP Terraform automatically started a new deployment run when you pushed your changes to your git repository. Click on the new deployment run under Recent versions if it is not already selected.
Under Deployment runs, HCP Terraform lists your dev, test, and prod deployments, as well as the current status of each. HCP Terraform plans changes to each deployment separately, and you can choose when to apply each plan.
Once HCP Terraform loads your new configuration, it automatically applies the change to your dev deployment, because there are no changes that affect it. HCP Terraform shows the new test and prod deployments as Pending approval.
Complete the following steps to deploy the test and prod environments:
- Click the ... button for
testand select Approve all plans. - Click Approve to confirm your approval when prompted.
- Click the ... button for
prodand select Approve all plans. - Click Approve to confirm your approval when prompted.
HCP Terraform deploys the new test and prod environments in parallel.
The existing dev environment was not affected by the change. To verify HCP Terraform did not change dev, click on dev. Expand the plan details by clicking View plan details and note that HCP Terraform shows No changes to the plan. HCP Terraform also shows that the plan was auto-approved, with a comment Auto-approval orchestrated by rule empty_plan. Examine the outputs and note they are unchanged.
After HCP Terraform successfully applies the test and prod environments, navigate to each environment and examine the outputs. Note each environment has a different timestamp in the manifest_contents output.
At this point, you have deployed your Stack to multiple environments from a single configuration. HCP Terraform manages each deployment independently, but you define them in one place.
If you got stuck at any point during this step, refer to the 03-add-deployments directory in the repository to see the configuration implemented for this step.
Add a component
Now, add a component to your Stack. The new component will use the pet-module module as its configuration source.
Open the modules/pet-module/main.tf file in your editor.
resource "random_pet" "pet" {
count = var.pet_count
length = 3
}
The pet-module defines a random_pet resource, which is provided by the hashicorp/random provider.
Open the components.tfdeploy.hcl file in your editor, add a new random provider and define the new pets component:
components.tfdeploy.hcl
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.8.1"
}
time = {
source = "hashicorp/time"
version = "~> 0.13.1"
}
}
provider "random" "this" {}
component "pets" {
source = "./modules/pet-module"
inputs = {
environment_name = var.environment_name
parent_directory = var.parent_directory
pet_count = var.pet_count
}
providers = {
random = provider.random.this
}
}
Update the inputs block of the manifest component to refer to the filenames produced by the pets component:
components.tfdeploy.hcl
component "manifest" {
source = "./modules/manifest-module"
inputs = {
parent_directory = var.parent_directory
environment_name = var.environment_name
additional_files = component.pets.pet_filenames
}
providers = {
time = provider.time.this
}
}
Open the variables.tfdeploy.hcl file in your editor, and define a new variable for the pet count
variables.tfdeploy.hcl
variable "pet_count" {
description = "Number of pets to create"
type = number
default = 1
}
Open the deployments.tfdeploy.hcl file in your editor, and set the pet_count value for the test and prod deployments:
deployments.tfdeploy.hcl
deployment "test" {
inputs = {
environment_name = "test"
pet_count = 4
}
}
deployment "prod" {
inputs = {
environment_name = "prod"
pet_count = 2
}
}
Open the outputs.tfdeploy.hcl file in your editor, and change the simulated_filesystem output to show pet_filenames:
outputs.tfdeploy.hcl
output "simulated_filesystem" {
description = "What the filesystem would look like"
value = concat([component.manifest.manifest_filename], component.pets.pet_filenames)
type = list(string)
}
After you update your configuration, run terraform stacks init to download the added provider and update the lockfile. Then, format and validate the configuration:
$ terraform stacks fmt
$ terraform stacks validate
.
Success! Terraform Stacks configuration is valid and ready for use within HCP Terraform.
Next, commit and push this change to your GitHub repository:
$ git add components.tfcomponent.hcl variables.tfcomponent.hcl deployments.tfdeploy.hcl outputs.tfcomponent.hcl .terraform.lock.hcl
$ git commit -m "Add new pets component"
$ git push
Return to your Stack in HCP Terraform and navigate to your Stack's Configurations page. Once HCP Terraform loads your configuration change, it shows all three deployments as Pending approval.
Navigate into your dev deployment where HCP Terraform shows the pending plan details. The configuration changes you pushed adds the pets component and changes two of the three output values.

Return to your Stack's Configurations page and complete the following steps to deploy your changes:
- Click the ... button for
devand select Approve all plans. - Click Approve to confirm your approval when prompted.
- Click the ... button for
testand select Approve all plans. - Click Approve to confirm your approval when prompted.
- Click the ... button for
prodand select Approve all plans. - Click Approve to confirm your approval when prompted.
HCP Terraform applies changes to all three environments in parallel. In practice, you would likely apply changes to a single environment and confirm the change worked as expected before applying changes to multiple environments.
Navigate to your dev deployment and examine the changes to the outputs. Your deployment added one new file to the simulated_filesystem output, because the default pet_count defined in variables.tfcomponent.hcl is 1, and pet_count is not set for the dev deployment in deployments.tfdeploy.hcl.
Navigate into your test environment and examine the changes to the outputs. Your deployment added four new files to the simulated_filesystem output, because pet_countis set to 4 in the test deployment in deployments.tfdeploy.hcl.
In this step, you added a component to all of your deployments at the same time, with different parameters for each deployment.
If you got stuck at any point during this step, refer to the 04-add-component directory in the repository to see the code implemented for this step.
Modify single deployment
Now, you will change an input for a single deployment.
Open the deployments.tfdeploy.hcl file in your editor, and add the following line to your dev deployment inputs block:
deployments.tfdeploy.hcl
deployment "dev" {
inputs = {
environment_name = "dev"
parent_directory = "non_default_directory"
}
}
# ...
Next, commit and push this change to your GitHub repository:
$ git add deployments.tfdeploy.hcl
$ git commit -m "Change parent directory for dev"
$ git push
Return to your Stack in HCP Terraform and navigate to your Stack's Configurations page. Once HCP Terraform loads your configuration change, it automatically plans the change to all three deployments.
HCP Terraform automatically applies the update to the test and prod environments because the change does not affect either environment. To verify HCP Terraform did not create, destroy, or modify any resources in either of these environments, click on the name of the environment. Examine the plans and outputs and note they are unchanged.
HCP Terraform also automatically applies the update to the dev deployment because the plan did not create, update, or destroy any resources. The plan only changed outputs.
Navigate to your dev deployment. Expand the Outputs details. The change to the parent_directory input caused both the manifest_filename and simulated_filesystem outputs to change.

In this step, you updated a single deployment, leaving others unchanged.
If you got stuck at any point during this step, refer to the 05-modify-deployment directory in the repository to see the code implemented for this step.
Destroy infrastructure
Now you have used a Terraform Stack to deploy three independent environments using a single Stack definition, added a component, and modified a single deployment.
Before finishing this tutorial, destroy your infrastructure.
Destroy deployments
To destroy a deployment, set that deployment's destroy argument to true and commit your configuration to your VCS. Destroy all three of the deployments you created in this tutorial.
Open deployments.tfdeploy.hcl and add destroy = true to each deployment:
deployments.tfdeploy.hcl
deployment "development" {
inputs = {
## ...
}
destroy = true
}
deployment "staging" {
inputs = {
## ...
}
destroy = true
}
deployment "production" {
inputs = {
## ...
}
destroy = true
}
Commit and push this change to your GitHub repository:
$ git add deployments.tfdeploy.hcl
$ git commit -m "Destroy all deployments"
$ git push
Return to your Stack in HCP Terraform and navigate to your Stack's Deployments page. Once HCP Terraform loads your configuration change, it creates a plan to destroy all three of your deployments. Navigate to each deployment and click the Approve plan button to destroy the resources for that deployment.
To verify that the virtual infrastructure created for a deployment was destroyed, navigate to the deployment. Notice that HCP Terraform removed the Output details. Click the View state button and observe that the state is now empty.
If you got stuck at any point during this step, refer to the 06-destroy directory in the repository to see the configuration implemented for this step.
Delete stack
Once you have destroyed all three of your deployments, navigate to your Stack's Settings > Destruction and Deletion page, and click the Delete button. Confirm the action, and click the Delete button.
Next steps
In this tutorial, you created virtual infrastructure in three environments using Terraform Stacks. You learned how the Stacks concepts of components and deployments build upon the traditional Terraform concepts of modules and workspaces, how to add a component to a Stack, how to apply changes to multiple environments in parallel with Stacks, and how to configure environments independently.
To learn more about Stacks, refer to the following resources:
- Study the
*.tfdeploy.hcland*.tfcomponent.hclfiles in this tutorial to understand how Stacks components, deployments, variables, and outputs fit together - Follow the Deploy a Stack tutorial to deploy real infrastructure to AWS, Azure, or GCP
- Review Stacks concepts by reading the Terraform Stacks, explained blog post
- Read the Stacks documentation
- Read the Stacks Use Cases documentation