Skip to content

Variables & Inputs

Variables and Inputs are an essential part of any Terraform project, allowing you to pass in data and configuration settings to your infrastructure resources.

In this section we’ll explore how to use variables and inputs in Terraform, including how to define, set them, and how to use them in your resource configurations.

Variables in Terraform are used to store and reference values that may change frequently, such as IP addresses or environment settings and allow us to define the parameterization of Terraform configurations.

They can have defaults, be provided with a variables file, asked for at execution, or overridden via the CLI. They can be strings or maps and must be defined before they’re used.

To define a variable, you can use the variable block in your Terraform configuration file, like this:

variable "region" {
type = string
default = "eu-west-2"
description = "The region name to use for the deployment"
}

This defines a variable called region, which is of type string and has a default value of eu-west-2. Using descriptions for variables helps describe the purpose of the variable and what type of value is expected.

If you don’t provide a default value - you must assign variables using the command line, when applying changes:

Terminal window
terraform apply -var="region=eu-west-2"

It is important to be aware that Terraform stores sensitive values in plain text in the state file. Therefore, the sensitive setting is simply designed to obscure values from logs and CLI output.

Often you need to configure your infrastructure using sensitive or secret information such as usernames, passwords, API tokens, or Personally Identifiable Information (PII). When you do so, you need to ensure that you do not accidentally expose this data in CLI output, log output, or source control.

For secrets, external secrets stores such as AWS Secrets Manager, AWS Systems Manager Parameter Store or HashiCorp Vault should be used instead.

Below is an example of configuring a variable with the sensitive setting set:

variable "password" {
type = string
sensitive = true
}

You can add validation blocks inside a variable to enforce rules on the values callers provide. Each block contains a condition expression that must evaluate to true and an error_message that Terraform displays when the condition fails.

variable "bucket_name" {
type = string
description = "Name of the S3 bucket"
validation {
condition = can(regex("^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$", var.bucket_name))
error_message = "Bucket name must be 3–63 characters, start and end with a lowercase letter or number, and contain only lowercase letters, numbers, hyphens, and periods."
}
}

A common pattern is restricting a variable to a fixed set of allowed values using contains:

variable "environment" {
type = string
description = "Target environment"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Environment must be one of: dev, staging, production."
}
}

You can also validate that a number falls within an acceptable range:

variable "instance_count" {
type = number
description = "Number of instances to create"
validation {
condition = var.instance_count >= 1 && var.instance_count <= 10
error_message = "Instance count must be between 1 and 10."
}
}

Cross-Variable Validation (Terraform 1.9+)

Section titled “Cross-Variable Validation (Terraform 1.9+)”

From Terraform 1.9 onwards, validation conditions can reference other variables, data sources, and locals — not just the variable being validated. This makes it possible to express rules that depend on multiple inputs:

variable "min_size" {
type = number
}
variable "max_size" {
type = number
validation {
condition = var.max_size >= var.min_size
error_message = "max_size must be greater than or equal to min_size."
}
}

For the full list of validation options, see the Custom Validation Rules documentation.

When you define a variable with an object type, every attribute is required by default. The optional() type modifier lets you mark individual attributes as optional so callers can omit them. You can also supply an inline default that Terraform applies automatically when the attribute is not provided.

variable "service" {
type = object({
name = string
enabled = optional(bool, true)
tags = optional(map(string), {})
})
description = "Service configuration"
}

In this example:

  • name is required — Terraform returns an error if the caller omits it.
  • enabled is optional and defaults to true when not supplied.
  • tags is optional and defaults to an empty map {} when not supplied.

A caller can provide only the attributes they care about:

service = {
name = "api"
}

Terraform fills in the missing attributes using the inline defaults, so the effective value becomes:

{
name = "api"
enabled = true
tags = {}
}

If you use optional() without a second argument — for example optional(bool) — the attribute defaults to null when omitted.

For the full details on the optional() modifier, see the Optional Object Type Attributes documentation.

To use a variable, reference it directly as var.<name>. The ${var.<name>} interpolation syntax is only needed inside quoted strings — for example, "prefix-${var.name}". Outside of strings, use the direct reference.

variable "ami_id" {
type = string
default = "ami-0c55b159cbfafe1f0"
}
variable "instance_type" {
type = string
default = "t2.micro"
}
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
}

Here we use the instance_type variable in our aws_instance resource.

A .tfvars file is a convenient way to store input variable values outside of your Terraform code. Simply create a file with the extension .tfvars and define your variables:

ami_id = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"

Variables and their associated values can be collected in files and passed all at once using the -var-file=foo.tfvars flag.

If a file named terraform.tfvars is present in the current directory, Terraform automatically loads it to populate variables.


This section covered how to define variables with types and defaults, mark variables as sensitive, reference them in resource configurations, and supply values through .tfvars files. These techniques let you parameterise your Terraform projects so the same configuration works across different environments.