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 uses HashiCorp configuration language (hcl).

Terraform Environment Variable Explained

A Terraform environment variable is similar to the parameter or argument of a function, allowing users to set their configuration without hardcoding values. This enables users to 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. The purpose of a Terraform tool is to have the same 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, instead of hardcoding these values and maintaining multiple copies of almost similar configuration, Terraform allows us to parameterize our configuration using environment variables.

More on Software DevelopmentHow to Set Environment Variables in Linux

 

How to Define Terraform Environment Variables

In order to use them you need to define them first inside a file somewhere in your configuration. The syntax for defining it is, as below:

 

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: Like 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: Like 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: Like 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
  …
}

Read OnBasic Probability Theory and Statistics Terms to Know

 

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.

  1. 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.
  2. 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. 
  3. Via shell variables with TF_VAR_ prefix: Terraform will read shell variable  TF_VAR_env=production and will set the value production to the variable env.  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.
  4. Via *.tfvars fileWe can have multiple files one for each environment like staging.tfvarsand production.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.
  5. 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

  1. To avoid code duplication for each environment.
  2. To store sensitive values outside the configuration, such as a database password.
An introduction on how to use Terraform variables. | Video: Corbus Bernard

 

More on Software EngineeringWhat Is TypeScript?

 

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 yanking the output on 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.

Expert Contributors

Built In’s expert contributor network publishes thoughtful, solutions-oriented stories written by innovative tech professionals. It is the tech industry’s definitive destination for sharing compelling, first-person accounts of problem-solving on the road to innovation.

Learn More

Great Companies Need Great People. That's Where We Come In.

Recruit With Us