EthicsComputerCourses
Join training +91 90532 10052

Input Variables & tfvars Files

Terraform & Ansible · Lesson 7 of 29 Intermediate 7 min read Updated

By the end of this lesson you will be able to declare input variables with types and validation, pass values in five different ways, and predict which value wins when the same variable is set twice. Variables turn a one-off configuration into something you can reuse for every city, team or environment.

Why variables

Look back at the file you created in the first lesson. The city name Rohtak was typed straight into main.tf. To make a notice for Jaipur, you had to edit the code.

An input variable is a named slot that is filled in when you run Terraform. A wedding card printer in Jaipur keeps one design and fills in different names and dates for each family. Variables let your configuration work the same way.

Step 1: Declare variables

By convention, variables live in a file called variables.tf. Create a new folder shop-notice with this file:

HCL (Terraform)
variable "shop_name" {
  type        = string
  description = "Name of the shop shown on the notice"
}

variable "city" {
  type    = string
  default = "Pune"
}

variable "discount_percent" {
  type    = number
  default = 10

  validation {
    condition     = var.discount_percent >= 0 && var.discount_percent <= 50
    error_message = "Discount must be between 0 and 50."
  }
}

Each variable block can have:

  • type: what kind of value is allowed (string, number, bool, list(string), map(number), object({...}) and more).
  • default: the value used if nobody sets one. A variable without a default is required.
  • description: a short explanation. Write one for every variable; it is the only manual most people read.
  • validation: a rule with a condition that must be true and an error_message shown when it is not.
  • sensitive: hides the value in plan output. You will use it in the security lesson.

Step 2: Use the variables

Refer to a variable with var.<name>. Add main.tf (with the same terraform block as in the first lesson):

HCL (Terraform)
resource "local_file" "notice" {
  filename        = "${path.module}/notice.txt"
  content         = "${var.shop_name}, ${var.city}: ${var.discount_percent}% off this Diwali!"
  file_permission = "0644"
}

Run terraform init, then terraform plan. Because shop_name has no default and you gave no value, Terraform asks for it:

Output
var.shop_name
  Name of the shop shown on the notice

  Enter a value: Sharma Sweets

Typing values at a prompt is fine for learning, but in real work you pass them in a repeatable way.

Step 3: Pass values in other ways

There are five common ways to set a variable.

1. The -var flag for a quick one-off value:

Terminal
terraform plan -var="shop_name=Sharma Sweets" -var="discount_percent=20"

2. A terraform.tfvars file, loaded automatically from the folder:

HCL (Terraform)
shop_name        = "Sharma Sweets"
city             = "Jaipur"
discount_percent = 15

3. Any file ending in .auto.tfvars, also loaded automatically, in alphabetical order.

4. A named file with -var-file, which is how teams keep one file per environment:

Terminal
terraform plan -var-file=diwali.tfvars

5. Environment variables named TF_VAR_ plus the variable name, which is handy in CI pipelines:

Terminal
export TF_VAR_shop_name="Sharma Sweets"
terraform plan

Which value wins?

When the same variable is set in several places, Terraform uses this order. Later items override earlier ones:

  1. The default in the variable block.
  2. Environment variables (TF_VAR_...).
  3. terraform.tfvars.
  4. terraform.tfvars.json.
  5. *.auto.tfvars and *.auto.tfvars.json files, in alphabetical order of file name.
  6. -var and -var-file options on the command line, in the order you type them.

So the command line always has the last word. Think of it like a school timetable: the printed timetable is the default, a notice on the board overrides it, and the principal's announcement on the day overrides everything.

Step 4: See validation in action

Try a discount that breaks the rule:

Terminal
terraform plan -var="discount_percent=80"
Output
│ Error: Invalid value for variable
│
│   on variables.tf line 10:
│   10: variable "discount_percent" {
│     ├────────────────
│     │ var.discount_percent is 80
│
│ Discount must be between 0 and 50.

The output is trimmed. Terraform stops before planning anything, and shows your own error message. Validation catches mistakes early, before they reach real infrastructure. Since Terraform 1.9, a validation condition may also refer to other variables, not only its own.

Complex types

Variables can hold structured data. An object type describes named fields, and optional() lets a field be left out, with an optional default:

HCL (Terraform)
variable "branches" {
  type = map(object({
    manager  = string
    counters = optional(number, 1)
  }))
  default = {
    jaipur  = { manager = "Isha", counters = 3 }
    lucknow = { manager = "Farhan" }
  }
}

Here lucknow gets counters = 1 from the optional default. Strong types give clear errors when someone passes the wrong shape, instead of a confusing failure deep inside a resource.

Common mistakes

  • Committing secrets in terraform.tfvars. Keep passwords and tokens out of tfvars files that go into Git. Use environment variables or a secrets manager.
  • Using any for every type. Precise types catch mistakes early.
  • Too many variables. If a value never changes, keep it in code. Every variable is one more thing to document and test.
  • Forgetting that *.auto.tfvars loads silently. An old file left in the folder can quietly change your plan.

Key points

  • Declare inputs with variable blocks; give each a type and a description.
  • A variable without a default is required; Terraform prompts for it if no value is given.
  • Set values with -var, -var-file, terraform.tfvars, *.auto.tfvars or TF_VAR_ environment variables.
  • Command-line values override files, which override environment variables, which override defaults.
  • validation blocks stop bad values before any plan is made.
  • Object types with optional() describe structured input clearly.

Exercise

Add a variable festival of type string with default "Diwali", whose validation allows only "Diwali", "Eid", "Christmas" or "Onam". Use it in the notice text. Then create onam.tfvars that sets the festival to Onam and the city to Kochi, and write the plan command that uses it.

Show solution
HCL (Terraform)
variable "festival" {
  type    = string
  default = "Diwali"

  validation {
    condition     = contains(["Diwali", "Eid", "Christmas", "Onam"], var.festival)
    error_message = "Festival must be Diwali, Eid, Christmas or Onam."
  }
}

In main.tf, change the content to end with off this ${var.festival}!. The onam.tfvars file holds festival = "Onam" and city = "Kochi".

Terminal
terraform plan -var-file=onam.tfvars -var="shop_name=Nair Stores"

contains() checks whether the list includes the value, so any other festival name fails validation with your message.

Quick Quiz

1. A variable has default = "Pune", terraform.tfvars sets "Jaipur" and you run -var="city=Kochi". Which value is used?

2. What happens when a variable has no default and no value is given?

3. Which environment variable sets the Terraform variable shop_name?

Learn Terraform & Ansible with a mentor

Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call