The cloud block in Terraform controls how your local configuration connects to HCP Terraform. While the basic setup is simple, there are several configuration options that most people never explore. The block sits inside the terraform block and replaces the remote backend pattern with a dedicated configuration surface for HCP Terraform connectivity, workspace selection, and host targeting. Understanding each attribute and how they interact with the rest of the terraform block is essential for reliable CLI workflows and migration from legacy remote backends.
Minimal Configuration
At its simplest, the cloud block needs just an organization and workspace.
hcl
terraform {
cloud {
organization = "acme-corp"
workspaces {
name = "api-server-prod"
}
}
}
That is all you need for a single workspace. Run terraform init and you are connected. This minimal form establishes the organization identity and pins the local run to a named workspace in HCP Terraform. No backend block is used at the same time.
The organization field is required and tells Terraform which HCP Terraform organization to use. It is the anchor for all subsequent operations. The workspaces block is required for selection and can target a workspace by name.
Full Option Set
Real-world setups usually need more flexibility. The cloud block can be written with every available option exposed.
hcl
terraform {
cloud {
# Required: your HCP Terraform organization name
organization = "acme-corp"
# Optional: defaults to app.terraform.io
# Set this for Terraform Enterprise installations
hostname = "app.terraform.io"
# Optional: authentication token
# Prefer terraform login or CLI credentials instead of hardcoding this
token = "your-api-token"
# Required: workspace selection (name OR tags, not both)
workspaces {
# Option 1: target a specific workspace
name = "api-server-prod"
# Option 2: target workspaces by tags (cannot use with name)
# tags = {
# service = "api-server"
# env = "prod"
# }
# Option 3: use a project to scope workspace selection
# project = "platform-team"
}
}
}
The example shows the four primary attributes that appear in the cloud block: organization, hostname, token, and workspaces.
Organization
Organization is required. It identifies the HCP Terraform organization the configuration belongs to. Without it the connection cannot be resolved.
Hostname
Hostname is optional and defaults to app.terraform.io. Set this for Terraform Enterprise installations where the control plane is self-hosted. The default preserves compatibility with HCP Terraform SaaS.
Token
Token is optional for authentication. Prefer terraform login or CLI credentials instead of hardcoding this. When supplied, it provides an API token for the connection.
Workspaces
Workspace selection is required. The workspaces block supports three modes:
- Name targeting: a specific workspace name is used.
- Tags targeting: workspaces are selected by tags, cannot be used with name.
- Project scoping: a project can be used to scope workspace selection.
The documentation shows tags as an array of strings in the reference example and as a map in the practical example. Both forms reflect the intent to select workspaces by tag attributes.
A summary of the cloud block attributes can be presented as:
| Attribute | Required | Default | Purpose |
|---|---|---|---|
| organization | Yes | - | HCP Terraform organization name |
| hostname | No | app.terraform.io | Control plane host, used for Terraform Enterprise |
| token | No | - | Authentication token, prefer login |
| workspaces.name | Conditional | - | Target a specific workspace |
| workspaces.tags | Conditional | - | Target workspaces by tags, mutually exclusive with name |
| workspaces.project | Optional | - | Scope selection to a project |
Terraform Block Context
The terraform block allows you to configure Terraform behavior, including the Terraform version, backend, integration with HCP Terraform, and required providers. The terraform block is the parent block that contains configurations that define Terraform behavior. You can only use constant values in the terraform block.
The attribute hierarchy inside the terraform block includes:
- required_version
- required_providers block
- provider_meta "
- backend "
" block | mutually exclusive with cloud - cloud block | mutually exclusive with backend
- experiments list
The reference definition shows a complete terraform block with built-in arguments:
hcl
terraform {
required_version = "<version>"
required_providers {
<PROVIDER> {
version = "<version-constraint>"
source = "<provider-address>"
}
}
provider_meta "<LABEL>" {
# Shown for completeness but only used for specific cases
}
backend "<TYPE>" {
# `backend` is mutually exclusive with `cloud`
"<ARGUMENTS>"
}
cloud {
# `cloud` is mutually exclusive with `backend`
organization = "<organization-name>"
workspaces {
tags = [ "<tag>" ]
name = "<workspace-name>"
project = "<project-name>"
}
hostname = "app.terraform.io"
token = "<TOKEN>"
}
experiments = [ "<feature-name>" ]
}
The cloud block is mutually exclusive with backend. You cannot define both in the same terraform block. This mutual exclusivity makes the migration path explicit.
Block Types in Terraform
Blocks are written in HashiCorp Configuration Language and allow you to declare resources, providers, variables, outputs, and other configuration elements within your Terraform code. Each block serves a specific purpose and has its own syntax and set of properties.
Common block types used in Terraform are:
- Terraform Block
- Provider Block
- Data Block
- Resource Block
- Module Block
- Variable Block
- Output Block
- Locals Block
The Terraform Block is used to define global configuration and behavior for terraform execution. It covers:
- Setting the required Terraform version
- Configuring the backend for storing the state file
- Defining experimental or optional features
- Specifying variables used across multiple modules or configurations
Example from the reference material:
hcl
terraform { required_version = ">= 0.12" backend "s3"
{ bucket = "terraform-state-bucket" key
= "terraform.tfstate" region = "us-west-2" } }
The Provider Block is used to configure and define the provider for a specific cloud or infrastructure program. It specifies details such as the provider name and version, authentication credentials, and other settings.
Cloud Block Versus Remote Backend
Terraform Cloud isn’t just a backend, it’s got a lot more services and features, including remote operations. Creating the cloud configuration block makes the difference clear and creates a migration path.
The other part is future updates and features. Instead of adding more arguments to the backend block that are Terraform Cloud specific, they can leave the backend block alone and introduce new options in the cloud block. What are those new options? No idea. But you can bet they’re coming soon.
The new cloud block in Terraform 1.1 provides an improved experience for those using the CLI workflow. Workspace names match between local and Terraform Cloud, and you can use tags to manage multiple workspaces. This change paves the way for future improvements in Terraform Cloud and the CLI experience. Migration from the remote backend is a simple affair as long as you remember to update the version of Terraform used by your workspaces.
Practical Patterns
The post covering every option available in the cloud block, when to use each one, and patterns that work well in practice emphasizes deep dive usage.
For a single environment, the minimal organization plus name pattern is sufficient.
For multi-workspace repos, tags allow a single configuration to map to multiple workspaces based on service and environment metadata. Project scoping adds an additional layer of organization inside HCP Terraform.
For Terraform Enterprise, hostname overrides the default SaaS endpoint. This keeps the same configuration shape while targeting an internal installation.
For authentication hygiene, token should be avoided in committed code. Terraform login or CLI credentials are preferred.
Configuration Table
| Concept | Details |
|---|---|
| Block purpose | Controls how local configuration connects to HCP Terraform |
| Parent block | terraform |
| Mutual exclusivity | cloud vs backend |
| Organization | Required |
| Hostname | Optional, defaults to app.terraform.io |
| Token | Optional, prefer login |
| Workspace selection | name OR tags, project optional |
Conclusion
The cloud block centralizes HCP Terraform connectivity inside the terraform block and replaces remote backend configuration with a purpose built surface. Organization is required and anchors the connection. Hostname provides Enterprise flexibility with a SaaS default. Token offers optional static auth but should be replaced by login workflows. Workspaces provide name, tag, and project based selection with clear mutual exclusion rules. The block is mutually exclusive with backend, enabling clean migration from remote backend patterns introduced in earlier Terraform versions.
The design choice to keep Terraform Cloud specific arguments out of the backend block gives room for future options without expanding backend complexity. Terraform 1.1 introduced the cloud block with matching workspace names and tag management, improving CLI workflows and setting a foundation for continued improvements. Understanding these attributes and their constraints ensures configurations remain portable, secure, and aligned with HCP Terraform capabilities.