Terraform is an infrastructure as code tool that lets you define cloud and on-premises resources in human-readable configuration files that you can version, reuse and share.
It can manage low-level components like compute, storage and networking resources, as well as high-level components like DNS entries and SaaS features. To do all this, Terraform configuration files are written in HashiCorp Configuration Language (HCL), a domain-specific language designed for human-readable infrastructure definitions.
Terraform supports defining input variables in configuration files using the variable
block, and setting their values externally using methods like environment variables, .tfvars
files or CLI options.
Terraform Environment Variable Explained
A Terraform environment variable is an external value — typically a shell variable prefixed with TF_VAR_
— that allow users to pass input into a Terraform configuration without hardcoding it. Similar to how function arguments work, they enable dynamic configuration by injecting values into defined input variables at runtime. This lets users have the same infrastructure provisioning across environments without requiring them to maintain multiple copies of almost-similar code.
Because we have to manage different instances of infrastructures living inside different environments like development, quality assurance (QA) or staging, it’s critical to provide the environmental context to your configuration without repeating the same code or polluting it with environment-specific hardcoded details. Terraform environment variables play a critical role in providing this abstraction.
Let’s dive into what environment variables are and how and when to use them.
What Is a Terraform Environment Variable?
Environment variables are like parameters or arguments of a function. They can be defined in a separate file and used throughout your configuration. Terraform enables consistent infrastructure provisioning across environments.
Still, there are a few things that will vary from one environment to another, such as database credentials, DNS, etc. So, to avoid hardcoding environment-specific values and maintaining multiple copies of almost similar configuration, Terraform allows us to parameterize our configuration using environment variables.
How to Define Terraform Environment Variables
In order to use them, you must first define them in a Terraform configuration file. The syntax for defining it is as follows:
Definition
variable <name> {
description = <optional description>
type* = <type of variable>
default = <optional default value>
}
Example
variable "env" {
description = "System environment name"
type = string
default = "development"
}
This block syntax defines a new variable by giving it a name, and the type keyword specifies its type. We can provide an optional description and default value (optional) using description and default keywords.
Terraform supports various types, which can be categorized as follows:
1. Primitive Types (string
, number
and bool
)
Definition:
variable "instance_type" {
type = string
default = "t2.micro"
}
Usage:
resource "aws_instance" "my-instance" {
...
"instance_type": var.instance_type,
...
}
2. Complex Types (list
or map
)
Definition:
variable "user_names" {
type = list(string)
default = ["user-1", "user-2"]
}
Usage:
resource "aws_iam_user" "iam-users" {
…
count = length(var.user_names)
name = var.user_names[count.index]
}
Definition:
variable "amis" {
type = map
default = {
"us-east-1" = "ami-z9aspap"
"us-west-1" = "ami-8sdsoi1"
}
}
Usage:
resource "aws_instance" "my-ec2-instance" {
…
ami = var.amis[var.region]
instance_type = "t2.micro"
}
3. User-Defined Types (object
)
Definition:
variable "rg_config" {
type = object({
create_rg = bool
name = string
location = string
})
}
Usage:
resource "azurerm_resource_group" "demo_rg" {
…
count = var.rg_config.create_rg ? 1 : 0
name = var.rg_config.name
location = var.rg_config.location
…
}
How to Use Terraform Environment Variables
Once you’ve defined a variable you can use or reference that variable in any part of your configuration. The syntax is, as follows:
Usage/Reference
var.<name>
Example
resource "aws_ecs_task_definition" "my-app-task" {
...
"image": "${var.env}.dkr.ecr.ap-south-1.amazonaws.com/${var.env}-my-app",
...
}
At run time, Terraform will replace var.name
with its value.
How to Set Terraform Environment Variable Values
The purpose of the environment variables is to provide the abstraction between the core infrastructure components, and their various environment-specific instances. So, we must set the values of these variables outside of the configuration at the time of plan/apply.
There are multiple ways to set the environment variables and each one has a different use case. So it’s not about picking one over another but using all these options in conjunction wherever applicable.
- Provide the default value in the variable definition itself using the default keyword: This is a great way to provide sensible defaults when one exists. But we should never use this option if the resource is environment specific and must be separate for each environment.
- Via a Terraform prompt at the time of apply/plan command: If no default value is present for the variable, Terraform will interrupt the apply/plan command for user input for these values. This option is used when we are actually testing the configuration and playing out with different values. The downside of using it in a production environment is that it may result in different infrastructure for each run, and doesn’t guarantee consistency.
- Via shell variables with
TF_VAR_
prefix: Terraform will read shell variableTF_VAR_env=production
and will set the valueproduction
to the variableenv
. This method is mostly used in CI/CD. This is a great way to provide environment secrets that must not be stored in your code repository in plain text format. - Via
*.tfvars file
: We can have multiple files one for each environment likestaging.tfvars
andproduction.tfvars
, and at the time of plan/apply, we can provide the path of the appropriate file using the-var-file
option. This option is good when we have to set several environment variables, and the values aren't sensitive and can be stored in the code repository. - Via
-var option
at the time of plan/apply command: This is an alternative way to provide values to the environment variables. This is useful when there aren’t many variables, and we are applying the configuration in a non-interactive fashion like CI/CD or through a script.
Terraform Environment Variable Use Cases
There are two major use cases for terraform environment variables
- To avoid code duplication for each environment.
- To store sensitive values outside the configuration, such as a database password.
Other Terraform Variables to Know
As with any other programming language, HCL also supports variables to make configuration more flexible and modular.
Local Variables
Local variables are like named constants defined in a program, they allow us to define some value that is needed in various parts of the configuration, and if that value changes we don’t have to make changes in all the places but only once.
The syntax for defining local variables is, as follows:
Definition
locals {
<variable_name_1> = <variable_value_1>
<variable_name_2> = <variable_value_2>
}
Example
locals {
algorithm = "aws:kms"
availability_zone = "US-East-1"
}
This block syntax defines local variables as a name-value pair.
Usage/Reference
Once defined, you can use/reference local variables using the below syntax
local.<variable_name>
Example
apply_server_side_encryption_by_default {
sse_algorithm = local.algorithm
}
While defining, it is “locals” (plural), but at the time of reference, it’s “local.<var_name>” (singular).
Output Variables
Output variables are like the return value of a statement. They allow us to store the values that terraform operations return, usually the ones which are not input and are generated by the back end system, like resource ID.
We can then use these values to pass on to other parts of the configuration or can be read outside the terraform config. There is also an option to mark these variables as sensitive and terraform will mask the value by default while displaying the output in the console and we need to read these values using terraform output command explicitly.
The syntax for defining output variables is as follows
Definition
output <name> {
value* = <terraform_operation_return_statement>
sensitive = <optional true|false>
}
Example
resource "aws_iam_access_key" "iam-key" {
user = aws_iam_user.admin-user.name
}
output "iam-key" {
value = aws_iam_access_key.iam-key
sensitive = true
}
This block syntax defines a sensitive output variable as a storage for the return value of the terraform config statement.
Usage/Reference
$ terraform output <name>
Example
terraform output iam-key
The above command will dereference the output variable and will return the actual return value of the original Terraform statement.
Frequently Asked Questions
What is a Terraform environment variable?
A Terraform environment variable is a value passed into a Terraform configuration to avoid hardcoding, enabling reusable and environment-specific infrastructure setups.
What are the different types of variables in Terraform?
Terraform supports primitive types (string, number, bool), complex types (list, map) and user-defined types (object) of variables.
How do I define a variable in Terraform?
To define a variable in Terraform, use the variable
block in your Terraform configuration. You can specify its type, a description and a default value. To set the value of a Terraform variable, set it via default values in the config, CLI prompts, shell variables (TF_VAR_name=value
), .tfvars
files or the -var
flag in CLI commands.