Terraform Environment Variables Explained

Published:
September 10, 2026

Terraform uses environment variables to adjust its behavior and configuration. Environment variables control various functions, including logging verbosity and input prompts, all without using HCL.

This article explains what Terraform environment variables are, why they matter, and how they differ from HCL Terraform variables.

Terraform Environment Variables Explained

Prerequisites

What Are Terraform Environment Variables?

Terraform environment variables are shell variables that Terraform reads at runtime to change its behavior. They are prefixed with TF_ and are set in a terminal session, shell profile, a CI/CD pipeline's settings, or a container's environment.

There are three variable subtypes:

  • TF_VAR_[name]. Supplies values to Terraform input variables.
  • TF_[name]. Controls Terraform's CLI/runtime behavior.
  • Provider-specific environment variables. Configures Terraform provider authentication and other provider-specific settings.

Terraform does not require setting variables inside any .tf file or configuration. It automatically picks up the values without an explicit reference in the configuration.

Why Are Terraform Environment Variables Important?

Environment variables separate how Terraform runs from what it manages. They enable the same Terraform configurations to run in different modes without changing the .tf files.

Terraform environment variables are essential for several reasons:

  • Portability. The same configuration behaves differently in different environments. Variables are code-independent and enable code reuse across local development, staging, and production.
  • Automation compatibility. CI/CD systems ignore interactive prompts. Environment variables provide inputs as needed, allowing Terraform to run unattended.
  • Debugging. Environment variables control log details through a shell-level toggle without altering or redeploying configuration.
  • Credentials and secrets. Provider credentials and sensitive inputs are often injected via environment variables to avoid hard-coding or committing them to version control systems.

Environment variables help keep Terraform configurations flexible, portable, and consistent across different environments.

Environment Variables vs. HCL Variables

Both environment variables and HCL variables configure Terraform. However, they reside in different places and have different roles.

The table below compares distinct aspects between environment and HCL variables.

AspectEnvironment VariablesHCL Variables
DefinitionShell, CI/CD settings, .env files..tf and .tfvars files.
DeclarationTF_VAR_[name] for input variables. TF_[name] for CLI behavior.variable "[name]" {[value]} blocks.
ScopeAffects entire Terraform process (CLI behavior, workspace, logging, etc.).Affects only the values passed into the configuration.
Version ControlNot committed.Often committed, except variable files that contain sensitive values.
PrecedenceTF_VAR_[name] is overridden by CLI arguments and variable files.The default argument is used when no other value is supplied through a higher-precedence source.
Use CaseCI/CD automation, storing secrets, workspace selection, logging.Declaring default configuration inputs.

HCL variables define a configuration accepts as input. Environment variables are one way to supply those inputs. Additional variables control Terraform CLI behavior and have no HCL equivalent.

Terraform Environment Variables Benefits

The main benefits of using environment variables are:

  • No secrets in code. Sensitive values passed through TF_VAR_[name] never appear in .tf or .tfvars files.
  • Consistent behavior. CI/CD pipelines can standardize logging, input handling, and workspaces across jobs without duplicating flags and commands.
  • Faster debugging. Some environment variables provide immediate and detailed insight into what Terraform and its providers are doing without adjusting configuration.

Note: Environment variables also help when provisioning Infrastructure as Code (IaC). Teams that run Terraform against phoenixNAP Bare Metal Cloud can use the TF_VAR_[name] pattern to pass PNAP_CLIENT_ID and PNAP_CLIENT_SECRET credentials.

Terraform Environment Variables: List

The table below shows every variable covered in this guide:

VariablePurpose
TF_VAR_[name]Sets the value of a declared input variable.
TF_LOGSets the logging verbosity level.
TF_LOG_PATHSets file path for logs.
TF_LOG_CORESets logging verbosity for Terraform's core engine.
TF_LOG_PROVIDERSets the logging verbosity for provider plugins.
TF_INPUTDisables interactive prompts for unset variables.
TF_IN_AUTOMATIONAdjusts CLI output for automated environments.
TF_CLI_ARGSAdds default arguments to every Terraform command.
TF_CLI_ARGS_[name]Adds default arguments to a specific Terraform command.
TF_DATA_DIRAdjusts the location of Terraform's working data directory.
TF_WORKSPACESelects an active workspace.
TF_CLI_CONFIG_FILEPoints Terraform to a custom configuration file.
TF_PLUGIN_CACHE_DIRSets a shared directory for caching provider plugins.
TF_REGISTRY_DISCOVERY_RETRYSets the retry count for registry discovery requests.
TF_REGISTRY_CLIENT_TIMEOUTSets the timeout in seconds for registry client requests.

Detailed explanations and examples are in the following sections.

TF_VAR_name

TF_VAR_[name] sets the value of an input variable from the environment. The variable has lower precedence than variable files and CLI arguments, but higher than the variable's default argument.

Provide the Terraform input variable name in the placeholder. For example, if the configuration file contains the following variables:

variable "region" {
  type    = string
  default = "us-east-1"
}

variable "instance_count" {
  type    = number
  default = 1
}

Set the variables using:

export TF_VAR_region=us-east-1

Export the second variable separately:

export TF_VAR_instance_count=2

Lastly, preview the changes with:

terraform plan
export tf_var_name terminal output

The variables set the ones declared in the configuration file, overriding the default values.

TF_LOG

The variable sets Terraform's logging verbosity. Accepted values are:

  • TRACE. The most verbose log level available. Provides detailed information for troubleshooting Terraform operations, such as internal code executions, state transitions, logic paths, and HTTP request/response bodies. Use for deep debugging or when working with HashiCorp support.
  • DEBUG. Highly detailed logs focused on operational flow. Shows developer-level details. Excludes low-level messages found in TRACE. Developers and administrators use this level to analyze unexpected behavior.
  • INFO. General, high-level operational logs. It logs major milestones and removes technical details found in DEBUG and TRACE. Useful when analyzing long-running executions.
  • WARN. Shows non-fatal warnings, deprecations, or suboptimal configurations. The warnings do not stop Terraform from running, but they point to future issues. Use this level when auditing the environment for best practices.
  • ERROR. Filters logs to show only error-level messages. It captures fatal events that prevent plan generation. Use it to quickly pinpoint an error when a CI/CD pipeline fails.

For example:

export TF_LOG=TRACE

Test with:

terraform plan
export tf_log trace terminal output

The output shows detailed logs in plain text.

Note: To turn off logging, clear the environment variable. Set it to an empty value or use unset [variable_name].

TF_LOG_PATH

Set the TF_LOG output to a file path using TF_LOG_PATH. Without the path, TF_LOG prints the result to the terminal.
For example, assuming TF_LOG is set to DEBUG, state the file path with:

export TF_LOG_PATH=./terraform.log

Apply with:

terraform apply
terraform tf_log_path terminal output

Save logs to a file to capture a full debug session for later analysis or when supplementing a support ticket.

TF_LOG_CORE

Controls the logging verbosity level for Terraform's core engine. It is separate from provider logging and captures only the core workflow (such as graph building, state operations, plan/apply logic).

It uses the same levels as the TF_LOG variable. For example:

export TF_LOG_CORE=TRACE

Run terraform plan:

terraform plan
export tf_log_core terminal output

The output shows core engine logs without provider logs.

TF_LOG_PROVIDER

Controls the logging verbosity for provider plugins, separate from core logging. Use this environment variable to isolate provider-specific issues.

For example:

export TF_LOG_PROVIDER=DEBUG

Apply with:

terraform apply
export tf_log_provider terminal output

The output shows provider logs without core engine logs. Unset TF_LOG_CORE to show only the provider logs in the output.

TF_INPUT

The variable controls Terraform's interactive prompts. When Terraform variables don't have a supplied value, Terraform prompts for any required input variables without a value.

terraform value prompt terminal output

Set the TF_INPUT variable to false or 0 to disable interactive prompts:

export TF_INPUT=0

Apply with:

terraform apply
export tf_input terminal output

The variable tells Terraform to stop asking for input interactively and instead throw an error. Use this feature to avoid hanging indefinitely for a non-interactive CI/CD job.

Note: The behavior is identical to passing an -input=false flag to every command.

TF_IN_AUTOMATION

The environment variable signals to Terraform that it is inside an automated environment or a CI/CD system. It adjusts human-readable output for automated environments.

terraform init with tip terminal output

When the value is non-empty, Terraform adjusts the human-readable output since the output is intended for automated environments rather than interactive use.

For example:

export TF_IN_AUTOMATION=1

Apply with:

terraform init
export tf_in_automation terminal output

The change is cosmetic and does not alter Terraform's behavior.

TF_CLI_ARGS

The variable appends arguments to every Terraform command invoked in the shell session. Arguments are added after the subcommand and before manually typed flags.

For example, change a variable using the TF_CLI_ARGS variable:

export TF_CLI_ARGS="-var=\"instance_count=99\""

Apply without variables:

terraform apply
export tf_cli_args terminal output

The output shows the environment variable appended to the terraform apply command.

TF_CLI_ARGS_name

To append additional arguments to a specific Terraform command, use TF_CLI_ARGS_[name]. For example:

export TF_CLI_ARGS_plan="-var=\"instance_count=99\""

The variable applies to the terraform plan command, while apply stays unaffected.

export tf_cli_args_plan terminal output

Use this approach when the flag applies to only one subcommand and to limit the scope.

TF_DATA_DIR

Terraform stores its per-working-directory data in a .terraform subdirectory of the current directory. Adjust the location with the TF_DATA_DIR environment variable:

export TF_DATA_DIR=./.my-hidden-cache

Initialize the project:

terraform init
export tf_data_dir terminal output

Keep the variable consistent across every command in a workflow (init, plan, apply) to avoid issues.

TF_WORKSPACE

Use TF_WORKSPACE to select the active Terraform workspace without running the terraform workspace select command:

export TF_WORKSPACE=default

Confirm the workspace change worked with:

terraform workspace list
export tf_workspace terminal output

The output shows a warning that the environment variable overrides the workspace.

TF_CLI_CONFIG_FILE

The variable points Terraform to a custom CLI configuration file instead of the default ~/.terraformrc (terraform.rc on Windows).

To demonstrate this setup, use mkdir -p to create a new directory and parent directories:

mkdir -p $HOME/tf-plugin-cache

Create a custom config file (ci.terraform in the example) and add the following data:

plugin_cache_dir = "/home/kb/tf-plugin-cache"

The file sets the plugin cache directory to a new location.

Export the custom config file as the new CLI config file:

export TF_CLI_CONFIG_FILE=./ci.terraform

Initialize the project:

terraform init

Lastly, list the tf-plugin-cache directory contents to confirm the reroute worked:

ls -R ~/tf-plugin-cache
export tf_cli_config_file terminal output

The output shows that Terraform read the local ci.terraform file and stored the plugin cache data in the tf-plugin-cache directory.

TF_PLUGIN_CACHE_DIR

Sets the directory Terraform uses to cache downloaded provider plugins. It prevents multiple configurations or repeated init runs from downloading the same provider binaries. For example, set the environment variable to a custom location:

export TF_PLUGIN_CACHE_DIR=$HOME/.terraform.d/plugin-cache
custom tf_plugin_cache_dir variable terminal output

Terraform uses this location to cache provider plugins. Use this variable in CI/CD environments to persist the plugin cache directory and reduce init time.

TF_REGISTRY_DISCOVERY_RETRY

The TF_REGISTRY_DISCOVERY_RETRY sets the maximum number of retries Terraform's registry client attempts for connection errors and retryable 500-range responses.

The default value is one, meaning there are no retries after the first attempt. Set it to five with:

export TF_REGISTRY_DISCOVERY_RETRY=5

Use the variable in environments with unreliable network paths.

TF_REGISTRY_CLIENT_TIMEOUT

Sets the timeout (in seconds) for requests made by Terraform's registry client during provider and module discovery.

The default value is 10 seconds. Set the timeout to 30 seconds with:

export TF_REGISTRY_CLIENT_TIMEOUT=30

Increase the variable in environments where registry requests are slow but succeed after some time.

How to Set Terraform Environment Variables Across Different OS?

The method for setting a Terraform environment variable depends on the underlying OS. The sections below briefly explain how to set environment variables on Linux, macOS, and Windows.

Linux and macOS

Linux and macOS use the same method for exporting Terraform environment variables. Use the export command for the current shell session:

export [variable_name]

To persist a variable across sessions, add the export line to the shell's profile file (.bashrc, .zshrc, or .profile in the home directory). Source the file after any change:

source ~/.bashrc

To avoid exporting a variable into a session, write the variable on the same line as the Terraform command it affects. For example:

TF_LOG=DEBUG terraform plan
tf_log terraform plan terminal output

The variable exists only for that command, not the terminal session.

Windows

Windows PowerShell uses $env: to set a variable for the current session. For example:

$env:TF_LOG = "DEBUG"

To persist a variable across sessions, use the following format:

[System.Environment]::SetEnvironmentVariable("[variable_name]", "[value]", "[user]")

For Command Prompt (cmd.exe), use the set command for the current session:

set TF_LOG=DEBUG

To persist a variable, use setx instead:

setx TF_LOG DEBUG

Alternatively, access the Environment Variables dialog through the UI.

How to Manage Terraform Environment Variables in CI/CD Pipelines

CI/CD pipelines use environment variables to add Terraform input variables. This lets you pass configuration at runtime instead of hard-coding values in files.

Terraform automatically recognizes environment variables using the TF_VAR_[variable_name] convention and maps them to the appropriate Terraform input variable.

For example, the following Terraform variables can be supplied with:

TF_VAR_region=eu-west-1
TF_VAR_instance_count=2

The variables let environment-specific configuration live outside the Terraform source code. It also enables testing different values for different CI/CD environments.

The sections below show how to configure Terraform variables with GitHub Actions, GitLab CI/CD, and HCP Terraform with Hashicorp Vault.

GitHub Actions Setup Example

GitHub Actions supports environment variables at the workflow, job, and individual step levels. Map the values to TF_VAR_[variable_name] so Terraform receives these values when the workflow runs.

For example, if the Terraform configuration defines the following variables without hard-coding default values:

variable "region" {
  type = string
}

variable "instance_count" {
  type = number
}

GitHub Actions workflow provides these values as variables and secrets:

name: Terraform

on: [push]

jobs:
  terraform:
    runs-on: ubuntu-latest

    env:
      TF_IN_AUTOMATION: "1"
      TF_INPUT: "0"
      TF_VAR_region: ${{ vars.TF_REGION }}
      TF_VAR_instance_count: ${{ secrets.TF_INSTANCE_COUNT }}

    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3

      - run: terraform init

      - run: terraform plan

The example code expects the vars and secrets values. To add these values, navigate to a project's Settings->Secrets and variables->Actions page and add each:

  • TF_REGION. A GitHub Actions repository variable.
GitHub Actions repository variables
  • TF_INSTANCE_COUNT. A GitHub Actions repository secret.
GitHub Actions repository secrets

Run the workflow to see the values in action.

run terraform plan GitHub Action variable and secret

GitHub masks the registered secret, while the variable value is visible in the logs.

GitLab CI/CD Pipeline Integration

GitLab CI/CD provides a similar mechanism through CI/CD variables. Configure the variables in the GitLab project instead of storing them directly in the .gitlab-ci.yml file.

Use the same Terraform configuration with GitLab:

variable "region" {
  type = string
}

variable "instance_count" {
  type = number
}

In GitLab, navigate to Settings->CI/CD->Variables page and click Add Variable to create variables.

GitLab CI/CD variables

Use the masking and visibility options to hide values in job logs and to protect variables. The .gitlab.ci.yml file does not contain the values, and they are configured as environment variables:

image:
  name: hashicorp/terraform:latest
  entrypoint: [""]

stages:
  - validate
  - plan

variables:
  TF_IN_AUTOMATION: "true"
  TF_INPUT: "false"

terraform_validate:
  stage: validate
  script:
    - terraform init
    - terraform validate

terraform_plan:
  stage: plan
  script:
    - terraform init
    - terraform plan

The pipeline doesn't hang waiting for interactive input, and it also hides sensitive values. Likewise, variables such as TF_IN_AUTOMATION and TF_INPUT help control an automated CI/CD workflow.

Terraform Cloud & HashiCorp Vault Integration

Terraform Cloud (HCP Terraform) supports both Terraform variables and environment variables in a workspace's variable settings.

HCP Terraform workspace variables

Use the "Sensitive" flag to prevent a value from displaying.

HCP Terraform workspace add Terraform variable

For dynamic secrets, HashiCorp Vault integrates with Terraform through the vault provider. It allows configurations to fetch short-lived credentials at runtime instead of reading them from a static environment variable. For example:

provider "vault" {
  address = "https://vault.example.com"
}

data "vault_generic_secret" "pnap_credentials" {
  path = "secret/data/pnap"
}

provider "pnap" {
  client_id     = data.vault_generic_secret.pnap_credentials.data["client_id"]
  client_secret = data.vault_generic_secret.pnap_credentials.data["client_secret"]
}

The pattern avoids storing credentials as an environment variable anywhere. Vault can issue short-lived credentials to Terraform when they are requested, depending on the configured secret engine and lease settings.

Best Practices for Sensitive Environment Variables

Implement best security practices to secure sensitive environment variables:

  • Don't commit ignore files. Don't commit .env files or shell profiles that contain secrets to a version control system, even if the repository is private. Instead, add them to ignore files to keep them private.
  • Mask/protect variables. Use CI/CD platform options to mask/protect variables. Avoid using plain variables for any private data.
  • Use ynamically issued credentials. Choose short-lived, dynamically issued credentials from a secrets manager whenever available.
  • Limit to protected branches. Restrict sensitive data to protected branches and environments. Don't expose secrets and credentials to all branches, forks, or pull request pipelines, and apply least-privilege principles.
  • Avoid printing. Higher debug levels and some commands leak secret values. CI/CD job logs expose these variables and make them readable.
  • Rotate credentials. Create new credentials and rotate them regularly. If you suspect exposure, rotate the credentials immediately.
  • Separate credentials. Use different credentials per environment (dev, staging, production). If credentials are leaked in one environment, the others stay protected.

Following these practices reduces the risk of exposing sensitive environment variables.

Terraform Environment Variables FAQs

The following sections answer some common questions about Terraform environment variables through hands-on examples.

How do I set Terraform environment variables for complex data types like maps or lists?

For complex types, such as lists or maps, use HCL literal syntax as a quoted string. For example, if the configuration file has the following:

variable "availability_zones" {
  type    = list(string)
  default = []
}

variable "tags" {
  type    = map(string)
  default = {}
}

Provide the list type with:

export TF_VAR_availability_zones='["us-east-1", "us-east-2"]'

Or the map type using:

export TF_VAR_tags='{ team = "delta", env = "dev" }'

Preview the values with:

terraform plan
export tf_var_name complex type terminal output

The process converts the literals to the appropriate type.

What happens if TF_LOG is set to an invalid level?

Terraform shows a warning that the level is invalid. It defaults to TRACE and shows available levels instead.

tf_log wrong level terminal output

The command does not fail or disable logging.

How do TF_CLI_ARGS environment variables interact with command line flags?

The TF_CLI_ARGS and TF_CLI_ARGS_[name] values insert directly after a subcommand and before any manually typed flags on the command line. For example:

export TF_CLI_ARGS_plan="--input=false"
terraform plan --input=true

The commands are equivalent to:

terraform plan --input=false --input=true

Manually typed flags always take precedence over the environment variables.

Does TF_VAR_ override values defined in terraform.tfvars?

The order in which values are checked in a Terraform CLI workflow is:

  • -var and -var-file arguments.
  • .auto.tfvars and *auto.tfvars.json files.
  • terraform.tfvars.json file.
  • terraform.tfvars file.
  • TF_VAR_[name] environment variables.
  • The default value in variable blocks.

Therefore, the opposite is true for a Terraform CLI workflow. HCP Terraform has additional variable and variable-set precedence rules. A value set in terraform.tfvars overrides a TF_VAR_[name] environment variable for the same variable name in the CLI.

How do I clear or unset a Terraform environment variable?

To unset a Terraform environment variable on Linux or macOS, use unset:

unset TF_[name]

For PowerShell, use:

Remove-Item Env:TF_[name]

In Command Prompt, clear a variable with:

set TF_[name]=

An empty value clears the variable for the session.

Can I use environment variables directly inside .tf HCL files?

HCL has no syntax for reading an environment variable by name. HCL configuration only reads the TF_VAR_[name] value and populates a declared variable "[name]" {} block.

All other environment variables are only visible to the Terraform CLI process. Expressions inside .tf files cannot access these variables.

Conclusion

This guide explained how to use various Terraform environment variables in different environments. Environment variables provide a convenient way to control CLI behavior, supply input values, and manage secrets without modifying configuration files.

Next, learn more about Terraform backends and how they work.

Was this article helpful?
YesNo