Terraform `cloud` backend ignores env vars

I am trying to configure my tiny piece of Terraform code to use the cloud{} backend.

Because this code is used in multiple TFE/TFC orgs, I am using the Environment Variables method to supply the config per https://developer.hashicorp.com/terraform/cli/v1.2.x/cloud/settings#environment-variables.

Code snippets:

terraform {
  required_version = ">= 1.2"

  # https://developer.hashicorp.com/terraform/cli/cloud/settings
  cloud {
    # cloud block is configured via env settings.
    # TF_CLOUD_ORGANIZATION
    # TF_CLOUD_HOSTNAME
    # TF_CLOUD_WORKSPACE
  }
  required_providers {
    # https://registry.terraform.io/providers/hashicorp/azurerm/latest
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
    # https://registry.terraform.io/providers/hashicorp/vault/latest
    vault = {
      source  = "hashicorp/vault"
      version = "~>3.7"
    }
  }
}

The required environment variables exist in my shell:

~azure-basic-test !3: set | grep TF_
TF_CLOUD_HOSTNAME=terraform-qa.redacted.cloud
TF_CLOUD_ORGANIZATION=redactedqa-org
TF_CLOUD_WORKSPACE=terraformPrototypes

When I run the terraform init in my shell, terraform says:

Initializing Terraform Cloud...
╷
│ Error: Invalid or missing required argument
│ 
│   on main.tf line 6, in terraform:
│    6:   cloud {
│ 
│ "organization" must be set in the cloud configuration or as an environment variable: TF_CLOUD_ORGANIZATION.

│ Error: Invalid workspaces configuration
│ 
│   on main.tf line 6, in terraform:
│    6:   cloud {
│ 
│ Missing workspace mapping strategy. Either workspace "tags" or "name" is required.
│ 
│ The 'workspaces' block configures how Terraform CLI maps its workspaces for this single
│ configuration to workspaces within a Terraform Cloud organization. Two strategies are available:
│ 
│ tags - A set of tags used to select remote Terraform Cloud workspaces to be used for this single
│ configuration. New workspaces will automatically be tagged with these tag values. Generally, this
│ is the primary and recommended strategy to use.  This option conflicts with "name".
│ 
│ name - The name of a single Terraform Cloud workspace to be used with this configuration.
│ When configured, only the specified workspace can be used. This option conflicts with "tags".

What am I missing here?

Resolved.

shell var != env var

I had a qa.env file which contained my variables.

TF_CLOUD_HOSTNAME=terraform-qa.redacted.cloud
TF_CLOUD_ORGANIZATION=redactedqa-org
TF_CLOUD_WORKSPACE=terraformPrototypes

I would then set them by doing source ./qa.env.
When I ran the set | grep TF_ it would display the variables as set.
What I learnt was that this only sets the variables in the current shell, NOT as environment variables.
I updated my qa.env to this:

export TF_CLOUD_HOSTNAME=terraform-qa.redacted.cloud
export TF_CLOUD_ORGANIZATION=redactedqa-org
export TF_CLOUD_WORKSPACE=terraformPrototypes

And ran my source ./qa.env. After that my terraform binary worked as advertised.

The question remains, why does terraform ignore variables set in a shell? Is that behaviour documented anywhere?

Hi @abest,

If I’m understanding your question correctly, I think it is not that Terraform is “ignoring” the values in the shell but instead that Terraform has no possible way to access them: they exist only in the memory space of the shell and not in the Terraform process.

When you use export as you showed here, it tells the shell that it should also set these environment variables when launching a child program like Terraform. That keyword is what gives the shell permission to share the value with the programs you run, and without it the value are visible only to expressions you write at the shell prompt or in shell scripts you run using source (which runs the scripts inside the same shell process where you typed the command, instead of starting a new child process for the shell).

This distinction is a feature of your shell and not of Terraform, and so Terraform itself has no control over it. Information about this will be in the documentation for your chosen shell, rather than in Terraform. (Different shells have different details about this, so it isn’t viable for Terraform’s docs to try to describe all possible shells.)