[November 20 Webinar] Detecting & Correcting Infrastructure Drift

➡️ Register Now

Terraform

How to Set & Use Terraform Environment Variables

An Introduction to Terraform Environment Variables

In this article, we will look at what Terraform environment variables are, when and why you would use them, and how to set them with examples of each! Let’s jump straight in!

We will cover:

  1. How to set the Terraform environment variables?
  2. How to read and use environment variables in Terraform runs?
  3. Different types of Terraform environment variables
  4. Custom environment variables in Terraform modules
  5. Example: Using provider-specific Terraform environment variables

What is a Terraform environment variable?

A Terraform environment variable is a key-value pair set within the environment where Terraform is running. Terraform refers to a number of environment variables to customize various aspects of its behavior. They can be used, for example, to specify the location of the Terraform configuration files, set provider credentials, or define backend configurations. These variables provide configuration information to Terraform without having to hardcode it into the configuration files.

How to set the Terraform environment variables?

Environment variables can be set on the command line, within scripts, or by using the operating system’s environment variable settings.

For reference, using the GUI in a Windows OS, they can be set Under System Properties → Advanced → Environment Variables → New system variable.

new system variable - terraform environment variables
new system variable TF LOG - terraform environment variables

On the command line in a Windows system, you can use the SET command as an equivalent to the export on Linux based system, and view the current value using %<variable name>%:

set TF_LOG=trace
%TF_LOG%

In Spacelift, environment variables can be defined directly on stacks and modules, as well as on contexts attached to those. Read more about using environment variables in our documentation.

How to read and use environment variables in Terraform runs?

To read and use environment variables in Terraform runs, you simply need to define a Terraform variable, and then add a value for it in the environment:

variable "name" {
   type = string
}

For example, if your variable is called name, as above, you will need to save its value in an environment variable called TF_VAR_name. Terraform checks the environment when you are running the code, and to ensure that you can name your variable however you want, it checks for names that are prefixed with TF_VAR.

Different types of Terraform environment variables

Terraform supports several types of environment variables that can be used to configure and manage different aspects of your infrastructure. Here are the main types of environment variables used in Terraform.

The following examples in this article use the export command, which is native to Linux and MacOS (but is not available on a Windows OS).

1) TF_VAR_name

As well as defining variables using a .tfvars files and directly on the command line, this environment variable can be used to set values for variables in your Terraform configuration.

Note that defining variables this way is a fallback if variable values are not found elsewhere.

The variable name you want to set the value for should be in the format _name, e.g., for a variable named region, you would specify TF_VAR_region as the variable name. This can be useful when running Terraform in automation, or when running a sequence of Terraform commands in succession with the same variables.

export TF_VAR_region=uksouth
export TF_VAR_regionlist='[uksouth,ukwest,useast2]'
export TF_VAR_tagmap='{ Environment = "dev", Project = "demo" }'

2) TF_LOG

The TF_LOG variable enables detailed logs in stderr, for debugging purposes:

export TF_LOG=trace

You can set TF_LOG to one of the log levels (in order of decreasing verbosity) TRACEDEBUGINFOWARN or ERROR to change the verbosity of the logs.

Setting TF_LOG to JSON outputs logs at the TRACE level or higher, and uses a parseable JSON encoding for formatting.

You can turn off logging when you have finished debugging:

export TF_LOG=off

3) TF_LOG_PATH

When TF_LOG is set, you can also use the TF_LOG_PATH variable to set the location where the log should persist its output to. The below example logs to a file called terraform.log in the local directory.

export TF_LOG_PATH=./terraform.log

4) TF_INPUT

TF_INPUT environment variable is useful when you want to replicate the -input=false flag behavior from the command line in an environment variable by specifying a value of 0 or FALSE. This disables prompts for input for variables that have not been specified.

export TF_INPUT=0

5) TF_CLI_ARGS and TF_CLI_ARGS_name

TF_CLI_ARGS is used to specify additional arguments to the command line. Arguments are inserted directly after the subcommand (such as plan) and before any flags specified directly on the command line. This behavior ensures that flags on the command line take precedence over environment variables.

For example, to run terraform plan with the debug mode enabled and specify the location of the state file, you can set the TF_CLI_ARGS variable to -state=terraform.tfstate -debug, which will pass the -state and -debug options to Terraform CLI.

export TF_CLI_ARGS="-state=terraform.tfstate -debug"

When the terraform plan command is run, Terraform uses the state file specified and outputs additional debugging information to the console.

A named command can also be specified, which will only affect that command. This is done using the TF_CLI_ARGS_name variable.

For example, to specify that only plans never refresh:

export TF_CLI_ARGS_plan="-refresh=false"

6) TF_DATA_DIR

By default, Terraform working data is written into a .terraform subdirectory of the current directory. The TF_DATA_DIR can be used to change the path where this data is held (useful in rare cases where the working directory is not writeable).

In automation, this must be set at each stage of the Terraform workflow for each command, e.g. terraform init , terraform plan , terraform apply — as each command will need to reference the working directory if it is changed from the default to find modules and configuration information.

export TF_DATA_DIR=./mydirectory/terraform

7) TF_WORKSPACE

This is the environment variable equivalent of setting your workspace using:

terraform workspace select my_workspace_name

This is useful in automation as it overrides any workspace selection but is not recommended when using Terraform interactively as it is easy to set and forget, which might cause inadvertent changes to the wrong Terraform state.

For example:

export TF_WORKSPACE=my_workspace_name

8) TF_IN_AUTOMATION

This is a variable used to set a purely cosmetic change to Terraform’s human-readable output, which prevents it from suggesting specific commands to run next after one command has been completed.

In automation, this wouldn’t be possible as the environment is non-interactive, so removing these suggestions makes the output less confusing. To use it, set it to any non-empty value.

export TF_IN_AUTOMATION=true

9) TF_CLI_CONFIG_FILE

Used to specify the location of the Terraform CLI configuration file. This is a file specified as .terraformrc or terraform.rc which configures per-user settings for CLI behaviors that apply across all Terraform working directories.

export TF_CLI_CONFIG_FILE=”./mydirectory/.terraformrc-custom”

10) TF_IGNORE

When debugging large repositories with .terraformignore files, the TF_IGNORE variable can be used to get Terraform to output debug messages to display ignored files and folders. It should be set to trace .

Files listed in a .terraformignore plan are simply a list of files that should not be considered as part of the configuration to speed up deployments when a large number of file exist.

export TF_IGNORE=trace

11) TF_REGISTRY_DISCOVERY_RETRY

Set TF_REGISTRY_DISCOVERY_RETRY to configure the max number of request retries, the remote registry client will attempt for client connection errors or 500-range responses that are safe to retry.

export TF_REGISTRY_DISCOVERY_RETRY=10

This example sets the value of TF_REGISTRY_DISCOVERY_RETRY to ten, which means that registry discovery operations will be retried up to ten times before failing.

12) TF_REGISTRY_CLIENT_TIMEOUT

This variable can be configured to increase the default client timeout to the remote registry during extraneous circumstances.

The default client timeout for requests to the remote registry is 10s.

export TF_REGISTRY_CLIENT_TIMEOUT=30

13) TF_STATE_PERSIST_INTERVAL

By default, Terraform persists the state to a remote backend every 20 seconds, but this value can be overridden by setting the TF_STATE_PERSIST_INTERVAL. Keep in mind that if you define a value lower than the minimum allowed for the backend, Terraform will default to the backend’s minimum interval. The value must be specified in seconds:

export TF_STATE_PERSIST_INTERVAL=50

14) TF_PLUGIN_CACHE_DIR

The TF_PLUGIN_CACHE_DIR is used to specify a directory where Terraform can cache provider plugins. This allows Terraform to reuse the same plugins across multiple projects or runs, rather than downloading them every time when terraform init runs.

export TF_PLUGIN_CACHE_DIR="$~/.terraform.d/plugin-cache"

Custom environment variables in Terraform modules

If you are using a module and when you are specifying the variables for it, you can add values to them with environment variables.

Let’s take a look at a simple example. Suppose you have the following module that generates random pet names:

resource "random_pet" "this" {
 prefix = var.prefix
}

variable "prefix" {
 type = string
}

Now, let’s call the module:

module "pet" {
   source = "./module"
   prefix = var.prefix
}

variable "prefix" {
 type = string
}

Next, let’s add an environment variable for the prefix:

export TF_VAR_prefix=dog

If we apply the code, we will see that our random pet name will be generated with the dog prefix we’ve set above:

+ resource "random_pet" "this" {
     + id        = (known after apply)
     + length    = 2
     + prefix    = "dog"
     + separator = "-"
   }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
 Terraform will perform the actions described above.
 Only 'yes' will be accepted to approve.

 Enter a value: yes

module.pet.random_pet.this: Creating...
module.pet.random_pet.this: Creation complete after 0s [id=dog-evolved-dane]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Example: Using provider-specific Terraform environment variables

For this example, we will use the AWS provider. There are many ways in which you can configure authentication, but we will explore the most basic one, which is using an access key and a secret key. This is what it looks like with hardcoded values:

provider "aws" {
 region     = "eu-west-1"
 access_key = "my-access-key"
 secret_key = "my-secret-key"
}

AWS gives us the ability to source the credentials in multiple ways (parameters in the provider configuration, environment variables, shared credentials files, and others). If we want to use environment variables, the AWS provider automatically reads values from the following variables:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN
  • AWS_REGION
  • AWS_DEFAULT_REGION

So you can set these if you’d like, by simply doing an export in your CLI. I will also show you how to configure custom ones by defining variables inside your Terraform configuration:

provider "aws" {
 region     = var.region
 access_key = var.access_key
 secret_key = var.secret_key
}

variable "region" {
   type = string
}

variable "access_key" {
   type = string
}

variable "secret_key" {
   type = string
}

Now to provide environment variables for these we could run the following in our terminal:

export TF_VAR_region="region"
export TF_VAR_access_key="access_key"
export TF_VAR_secret_key="secret_key"

Ensure you change the values to the ones from your AWS account, and that’s it.

Why use Spacelift with Terraform?

Terraform is really powerful, but to achieve an end-to-end secure GitOps approach, you need to use a product that can run your Terraform workflows. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:

  • Policies (based on Open Policy Agent) — You can control how many approvals you need for runs, the kind of resources you can create, and the kind of parameters these resources can have, and you can also control the behavior when a pull request is open or merged.
  • Multi-IaC workflows — Combine Terraform with Kubernetes, Ansible, and other IaC tools such as OpenTofu, Pulumi, and CloudFormation, create dependencies among them, and share outputs
  • Build self-service infrastructure — You can use Blueprints to build self-service infrastructure; simply complete a form to provision infrastructure based on Terraform and other supported tools.
  • Integrations with any third-party tools — You can integrate with your favorite third-party tools and even build policies for them. For example, you can integrate security tools in your workflows using Custom Inputs.

Spacelift enables you to create private workers inside your infrastructure, which helps you execute Spacelift-related workflows on your end. The documentation provides more information on configuring private workers.

If you want to elevate your Terraform management, create a free account for Spacelift today or book a demo with one of our engineers.

Key points

Terraform environment variables provide a flexible and secure way to manage configuration information, making it easier to use Terraform in a variety of environments and scenarios.

Environment variables are not required when using Terraform, but they can be helpful to change some of Terraform’s default behaviors in unusual situations.

Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Achieve Terraform at Scale

Spacelift effectively manages Terraform state, more complex workflows, supports policy as code, programmatic configuration, context sharing, drift detection, resource visualization and includes many more features.

Learn more

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide