Input Variables & tfvars Files
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:
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 aconditionthat must be true and anerror_messageshown 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):
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:
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:
terraform plan -var="shop_name=Sharma Sweets" -var="discount_percent=20"2. A terraform.tfvars file, loaded automatically from the folder:
shop_name = "Sharma Sweets"
city = "Jaipur"
discount_percent = 153. 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:
terraform plan -var-file=diwali.tfvars5. Environment variables named TF_VAR_ plus the variable name, which is handy in CI pipelines:
export TF_VAR_shop_name="Sharma Sweets"
terraform planWhich value wins?
When the same variable is set in several places, Terraform uses this order. Later items override earlier ones:
- The
defaultin the variable block. - Environment variables (
TF_VAR_...). terraform.tfvars.terraform.tfvars.json.*.auto.tfvarsand*.auto.tfvars.jsonfiles, in alphabetical order of file name.-varand-var-fileoptions 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:
terraform plan -var="discount_percent=80"│ 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:
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
anyfor 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.tfvarsloads silently. An old file left in the folder can quietly change your plan.
Key points
- Declare inputs with
variableblocks; give each atypeand adescription. - A variable without a
defaultis required; Terraform prompts for it if no value is given. - Set values with
-var,-var-file,terraform.tfvars,*.auto.tfvarsorTF_VAR_environment variables. - Command-line values override files, which override environment variables, which override defaults.
validationblocks 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
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".
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?
Command-line -var values override tfvars files and defaults.
2. What happens when a variable has no default and no value is given?
A variable without a default is required.
3. Which environment variable sets the Terraform variable shop_name?
Terraform reads environment variables named TF_VAR_ followed by the variable 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
