DEV Community

quixoticmonk
quixoticmonk

Posted on

Mastering Terraform Stacks: Post-GA Command References Part 1

This post builds on my previous article Terraform Stacks: A Revisit, where I reviewed what Terraform Stacks had evolved to from an idea or beta. The concept of having that layer of abstraction around deployment was novel and I am still looking forward to some of the improvements we will see in the future. In this post, I am looking to review the terraform stacks subcommand in detail based on the updates from HashiConf. Some of the updates actually broke some live demo plans of some fellow HashiCorp ambassadors on Day 2 of HashiConf :) You know who you are.

Anyone wanting a good reference of the changes from beta to General availability(GA) should read the official documentation here. I do feel there are some elements missing or scattered around the documentation elsewhere which could have been surfaced up better. At a high level, terraform stacks subcommand provides a comprehensive set of options organized into primary operations for configuration, deployment groups, and deployment runs.

Prerequisites and Setup

Before diving into the commands, you'll need an active HCP Terraform setup. This includes setting up an HCP Terraform organization, creating a project ( or use the Default Project ) within that organization, and generating a token with appropriate permissions for stack operations. The CLI relies on specific environment variables including TF_STACKS_ORGANIZATION_NAME,TF_STACKS_PROJECT_NAME ,TF_STACKS_STACK_NAME , and TF_TOKEN_app_terraform_io for authentication and targeting the correct resources if not explicitly provided in the commands as arguments or options.

Building on the examples from my previous post, we'll explore the foundational commands that every Terraform Stacks workflow begins with. The terraform stacks init command prepares your configuration directory, while providers-lock ensures consistent provider versions across environments. The validate command checks your configuration syntax before deployment. These commands form the foundation that enables the more advanced operations covered in the following sections.

Note: I have terraform aliased to tf.

If you run terraform stacks post GA, you would see these additional subcommands for configuration, deployment-group and deployment-run. It would be a miss not to introduce these without which the post will be difficult to comprehend.

tf stacks
Usage: terraform stacks [global options] <command> [args]

The available commands for execution are listed below.

Primary Commands:
  init              Prepare the configuration directory for further commands
  providers-lock    Write out dependency locks for the configured providers
  validate          Check whether the configuration is valid
  create            Create a stack
  list              List stacks for a given organization and/or project.
  version           Show the current Stacks Plugin version
  fmt               Reformat your Terraform Stacks configuration to a canonical format


Sub-commands:
  configuration     Manage stack configuration
  deployment-group  Manage deployment groups
  deployment-run    Manage deployment runs


Global options (use these before the subcommand, if any):
  -chdir=DIR              Switch to a different working directory before executing the
                          given subcommand.
  -plugin-cache-dir=DIR   Override the default directory where the stack plugin binary is cached.
  -stacks-version         An alias for the "version" subcommand.
  -no-color=BOOL          Disable color output. Must be explicitly set to true or false.

Usage help:
  -usage                  Show this usage output or the usage for a specified subcommand.
                          Use after the command: terraform stacks <command> -usage


Enter fullscreen mode Exit fullscreen mode
  • Components : is a replacement of modules in a way; though it is more than modules.Translates to what infrastructure, or components, should be part of the Stack.
  • Deployments : Where and how many times to deploy the infrastructure in the Stack.
  • Deployment Groups : Combine a set of deployment targets into a group. Allows to set some specific approval rules for each deployment groups based on specific contextual conditions.
  • Configuration : Everything including the above with the terraform version , lock files which make up a Stack

General notes before we dive in

I do like the -json usage across the subcommands. May be we are gearing up to a usage of these commands from an agent :)

Note: Can we get some short form syntaxes for these subcommand options already please ?

Create a Stack from your terminal

I somehow feel this command is a little incomplete as it stands now. I am ignoring the global options as they are the same 4 always across Stacks' subcommands. Lets create a Stack in three different variants and see what it translates to in the HCP Terraform UI.

Option 1

tf stacks  create  -organization-name ne-devops -project-name "Default Project" -stack-name "manu-option1"
Creating stack...
Stack: Created stack 'manu-option1'
Enter fullscreen mode Exit fullscreen mode

The result is ...

Reviewing the settings..

Option 2

tf stacks  create  -organization-name ne-devops -project-name "Default Project" -stack-name "manu-option2" -with-template
Creating stack...
Stack: Created stack 'manu-option2'
Creating example stacks configuration...
Stack: Created example stack configuration for 'manu-option2'

Enter fullscreen mode Exit fullscreen mode

The result is ...

Reviewing the settings...

I do not see a difference in the stack created on the HCP Terraform UI with the -with-template option supplied with the terraform stacks create command. Now the argument reads as below

 -with-template      Generate boilerplate configuration

Enter fullscreen mode Exit fullscreen mode

May be it is a placeholder for more things to come.

Option 3

Though this is more of a variant only in terms of how the data is presented back to the user on the completion of a command, I see the value when it comes to passing these logs to some external systems or even to an operations agent.

tf stacks  create  -organization-name ne-devops -project-name "Default Project" -stack-name "manu-option3" -json
{"@level":"info","@message":"Creating stack","@module":"terraform.stacks.ui","@timestamp":"2025-10-01T21:29:06.137667-04:00","format_version":"1.0","type":"create_in_progress"}
{"@level":"info","@message":"Created stack","@module":"terraform.stacks.ui","@timestamp":"2025-10-01T21:29:06.421967-04:00","format_version":"1.0","type":"create_success"}

Enter fullscreen mode Exit fullscreen mode

What am I missing ?

The stacks which are created are barebones at this point. What would make this command wholesome is the ability to associate the stacks with a VCS connection and to be able to start that first run of the configuration fetch that way.

List the stacks

Lets run the stacks list without any arguments on a new terminal.

tf stacks list
╷
│ Error: Missing required flag `-organization-name`
│
│ Please provide the `-organization-name` flag with the name of the target organization.
│ Alternatively, set the ENV VAR 'TF_STACKS_ORGANIZATION_NAME'.
╵
Failure! Could not list stacks

Enter fullscreen mode Exit fullscreen mode

As expected, we do see the need to specify the Organization name.

tabular format


tf stacks list -organization-name ne-devops
        Stack Name        |         Stack ID         |        Created At        |        Updated At        |
       manu-option2       |   st-Y2J3wa6yKBSP83Hc    |    Oct 02, 2025 13:02    |    Oct 02, 2025 13:02    |
       manu-option1       |   st-31HY1439bDRVawex    |    Oct 02, 2025 13:00    |    Oct 02, 2025 13:00    |
        app-stack         |   st-g7uPLPR4pnWyvT7e    |    Oct 01, 2025 17:44    |    Oct 01, 2025 17:44    |
   manuchn-stacks-2025    |   st-jcgFCdyai89kcn5S    |    Sep 30, 2025 14:08    |    Sep 30, 2025 14:08    |
     pet-nulls-stack      |   st-uyBoA811rPgNzvw3    |    Sep 08, 2024 04:41    |    Sep 08, 2024 04:41    |
  external_module_stack   |   st-wfXoXu2a56n3GC4Y    |    Mar 09, 2024 22:00    |    Mar 09, 2024 23:09    |
     pet-nulls-stack      |   st-M6kzAWsw7e7Ldep8    |    Feb 28, 2024 22:57    |    Feb 28, 2024 22:59    |

Enter fullscreen mode Exit fullscreen mode

json format

I was thinking the stacks list would benefit from a column project till I ran the -json format. The data doesn't seem to be present in the output.

tf stacks list -organization-name ne-devops -json
{"format_version":"1.0","organization_name":"ne-devops","project_id":"","stacks":[{"created_at":"2025-10-02T13:02:49Z","id":"st-Y2J3wa6yKBSP83Hc","name":"manu-option2","updated_at":"2025-10-02T13:02:49Z"},{"created_at":"2025-10-02T13:00:22Z","id":"st-31HY1439bDRVawex","name":"manu-option1","updated_at":"2025-10-02T13:00:22Z"},{"created_at":"2025-10-01T17:44:34Z","id":"st-g7uPLPR4pnWyvT7e","name":"app-stack","updated_at":"2025-10-01T17:44:34Z"},{"created_at":"2025-09-30T14:08:37Z","id":"st-jcgFCdyai89kcn5S","name":"manuchn-stacks-2025","updated_at":"2025-09-30T14:08:37Z"},{"created_at":"2024-09-08T04:41:32Z","id":"st-uyBoA811rPgNzvw3","name":"pet-nulls-stack","updated_at":"2024-09-08T04:41:32Z"},{"created_at":"2024-03-09T22:00:44Z","id":"st-wfXoXu2a56n3GC4Y","name":"external_module_stack","updated_at":"2024-03-09T23:09:22Z"},{"created_at":"2024-02-28T22:57:52Z","id":"st-M6kzAWsw7e7Ldep8","name":"pet-nulls-stack","updated_at":"2024-02-28T22:59:54Z"}]}
Enter fullscreen mode Exit fullscreen mode

Filter by project

All the stacks I had listed were part of the Default Project anyway. So it is not not going to show any difference here.

❯ tf stacks list -organization-name ne-devops -project-name "Default Project"
        Stack Name        |         Stack ID         |        Created At        |        Updated At        |
       manu-option2       |   st-Y2J3wa6yKBSP83Hc    |    Oct 02, 2025 13:02    |    Oct 02, 2025 13:02    |
       manu-option1       |   st-31HY1439bDRVawex    |    Oct 02, 2025 13:00    |    Oct 02, 2025 13:00    |
        app-stack         |   st-g7uPLPR4pnWyvT7e    |    Oct 01, 2025 17:44    |    Oct 01, 2025 17:44    |
   manuchn-stacks-2025    |   st-jcgFCdyai89kcn5S    |    Sep 30, 2025 14:08    |    Sep 30, 2025 14:08    |
  external_module_stack   |   st-wfXoXu2a56n3GC4Y    |    Mar 09, 2024 22:00    |    Mar 09, 2024 23:09    |
     pet-nulls-stack      |   st-M6kzAWsw7e7Ldep8    |    Feb 28, 2024 22:57    |    Feb 28, 2024 22:59    |


❯ tf stacks list -organization-name ne-devops -project-name "experiments"
        Stack Name        |         Stack ID         |        Created At        |        Updated At        |


Enter fullscreen mode Exit fullscreen mode

Tying this back to the HCP Terraform UI; why is Stacks not an entity of its own similar to the workspaces ?

Configuration related

As we are peeling the layers of the Stacks onion, we have till now looked at adding the Stacks frame onto the HCP Terraform organization. But it is missing any sort of configuration items to provision any infrastructure to a target platform.

Note: I have configured a variableset on my HCP Terraform organization with an IAM role which allows any stacks in my org to provision some resources ( S3, VPCs) if they fall under my HCP Terraform organization. I am not going to dive into that as that OIDC based setup hasn't changed from the time of beta.

The commands below are run on a directory which has my HashiConf-Stack repo cloned. So this command is supposed to supplement the stacks create in my mind. For most of the commands below, a stack is the frame of reference. So you need either a combination of organization-name, project-name, stack-name or stack-id. I do wonder why we need the project name since we can list the stacks without a project reference in the stacks list command.

list

I am going to use one of the stack ids from the create operations we did earlier. As expected, there are no configuration items associated with the stack manu-option1 at this point.

> tf stacks configuration list -stack-id st-31HY1439bDRVawex
     Sequence Number      |     Configuration ID     |


> tf stacks configuration list -stack-id st-31HY1439bDRVawex --json
{"configurations":null,"format_version":"1.0","stack_id":"st-31HY1439bDRVawex"}
Enter fullscreen mode Exit fullscreen mode

Upload

Running this from a non-stacks directory.

tf stacks configuration upload -stack-id st-31HY1439bDRVawex
╷
│ Error: Missing .terraform-version file
│
│ Terraform Stacks requires a .terraform-version file alongside the root .tfcomponent.hcl files.
╵
╷
│ Error: Failed to open source bundle
│
│ Failed to open source bundle: cannot read manifest: open /Users/manuchn/Documents/2025/TFC/Hashi/experiments/manuchandrasekhar.com/.terraform/modules/terraform-sources.json: no such file or directory. You may need to run `terraform stacks init`.
╵
failed to upload stack configuration

Enter fullscreen mode Exit fullscreen mode

So , you need to initialize the stack , provide a lock configuration and a terraform version. We didn't specify a terraform version when we created the stack using the cli, which I believe doesn't have a version association till a configuration is uploaded.

tf stacks init
Provider "hashicorp/aws" already locked at "5.100.0".
Provider "hashicorp/random" already locked at "3.7.2".
Downloading "hashicorp/aws"@"5.100.0"....
Downloading "hashicorp/random"@"3.7.2"....
Success! Configuration has been initialized and more commands can now be executed.

❯ tf stacks configuration upload -stack-id st-31HY1439bDRVawex
Uploading stack configuration...

Configuration for Stack (id: 'st-31HY1439bDRVawex') was uploaded
Configuration ID: stc-S5Sr3y57SWDLd5G5
Sequence Number: 1

See run at: https://app.terraform.io/app/ne-devops/projects/prj-qbcM8hb5k4EUCGj4/stacks/st-31HY1439bDRVawex/configurations-ga/stc-S5Sr3y57SWDLd5G5


Enter fullscreen mode Exit fullscreen mode

The url which has the configuration or run leads you to the page below if you open the configuration 1

Note: You do not see an apply creating resources as I had destroy=true set on the deployments for the first time.

Subsequently a configuration list renders the below.

tf stacks configuration list -stack-id st-31HY1439bDRVawex
     Sequence Number      |     Configuration ID     |
            1             |   stc-S5Sr3y57SWDLd5G5   |

Enter fullscreen mode Exit fullscreen mode

Note: I have seen some glitches here where the Configurations remain blank even when there is an active configuration. This could be some caching issues on my browser.

Let's re-run the configuration upload with the destroy=true removed in the tfdeploy.hcl file. I did make a mistake on my configuration and had to run the configuration upload twice. So you will see configuration versions up to 3 in the list when we do those. With the auto-approve on:

Diving into the deployment in HCP Terraform, you can see that the resources have been created in my target AWS account using the configuration upload without a VCS connection.

The state from the Stacks standpoint is slightly different from how you are used to from a workspace or pre-GA.

The command configurations upload has this option speculative which can prevent triggering any deployments via this configuration upload. Lets try this again with the option set to true.

tf stacks configuration upload -stack-id st-31HY1439bDRVawex -speculative
Uploading stack configuration...

Speculative Configuration for Stack (id: 'st-31HY1439bDRVawex') was uploaded
Configuration ID: stc-PbHnPRArTLBABzCC

See run at: https://app.terraform.io/app/ne-devops/projects/prj-qbcM8hb5k4EUCGj4/stacks/st-31HY1439bDRVawex/configurations-ga/stc-PbHnPRArTLBABzCC

Enter fullscreen mode Exit fullscreen mode

My issue here is with the phrasing on the option speculative. You are triggering a deployment run under a configuration null. I believe this maps to a speculative plan run on workspaces. I think this should be updated to state that explicitly than using the word deployment here.

-speculative: Upload will be speculative and will not trigger any deployments.

Enter fullscreen mode Exit fullscreen mode

Note: I hope they have an option to see this as a json with some download options.

Watch

This is your command line equivalent of live loading on the HCP Terraform UI or the kubectl watch command.

 tf stacks configuration upload -stack-id st-31HY1439bDRVawex
Uploading stack configuration...

Configuration for Stack (id: 'st-31HY1439bDRVawex') was uploaded
Configuration ID: stc-e6dfkfXL3HgDq1U2
Sequence Number: 4

See run at: https://app.terraform.io/app/ne-devops/projects/prj-qbcM8hb5k4EUCGj4/stacks/st-31HY1439bDRVawex/configurations-ga/stc-e6dfkfXL3HgDq1U2

❯ tf stacks configuration watch -configuration-id stc-e6dfkfXL3HgDq1U2

Enter fullscreen mode Exit fullscreen mode

Entering the command launches you to a watch interface which looks to provide you with a real time update on what is happening with the configuration or deployment. Keep in mind that I have the auto-approve set on the deployment groups which is making the response below skip a Pending state.


[Configuration Sequence Number: 4]
  ✓ Configuration: 'stc-e6dfkfXL3HgDq1U2'                   [Completed]        [24s]
    - Deployment Group: 'test_stack'                        [Deploying]        [33s]

Press q to quit

....


[Configuration Sequence Number: 4]
  ✓ Configuration: 'stc-e6dfkfXL3HgDq1U2'                   [Completed]        [24s]
    ✓ Deployment Group: 'test_stack'                        [Succeeded]        [37s]

Press q to quit


Enter fullscreen mode Exit fullscreen mode

There are additional commands in the configuration side including fetch which requires a VCS connection. I am going to bundle that along the VCS based setup in a different post.

Environment Setup

I could possibly have set these below environment variables than having to add those options in all my commands. But I preferred to know what I am working with , this time around. Maybe in a CI based environment, the environment variable setup would come in handy.

export TF_STACKS_ORGANIZATION_NAME="ne-devops"
export TF_STACKS_PROJECT_NAME="Default Project"
export TF_STACKS_STACK_NAME="app-stack"
Enter fullscreen mode Exit fullscreen mode

Conclusion

With the recent updates , Terraform Stacks provides a unified CLI experience for managing deployments directly against HCP Terraform organizations, offering an alternative to VCS-based deployment workflows. I hope that current implementation gaps will be addressed as platform teams adopt Stacks for managing baseline infrastructure that development teams build upon. As I have always said, Stacks introduces new approaches for provisioning foundational infrastructure across target platforms. However, documented post-GA limitations currently restrict broader adoption in scenarios like AWS OU-based deployments that would typically use StackSets or something similar.

  • HCP Terraform supports up to a maximum of 20 deployments for a Stack.
  • Deployment groups currently support a single deployment for a Stack.

I planned to write about deployment groups and runs. But with the length of the post, I felt it is better to break this into a few different posts.

Top comments (0)