Input Variables
Input variables are a configuration's parameters — the values you change between environments or runs without editing the code. A variable block declares one; var.name reads it. Variables are how a single configuration serves dev and prod, how a module exposes a clean interface, and how environment specifics stay out of the committed code.
The thing that trips people up is not the syntax — it is where a value actually comes from. Terraform reads a variable from several sources with a strict precedence, and a surprising number of "why is it using the wrong region?" sessions end with someone discovering a -var flag or a stray .auto.tfvars file was winning.
Declaring a Variable
A variable block has three fields worth setting on every declaration: type constrains what callers may pass, default makes the variable optional by supplying a fallback, and description documents the interface. The block below declares an instance type that defaults to t3.micro and a required environment name with no default.
variable "instance_type" { type = string default = "t3.micro" description = "EC2 instance type for the app servers" } variable "environment" { type = string description = "Deployment environment: dev, staging, or prod" }
Reading a Variable
You reference a variable anywhere a value is allowed with var.name. There is no special interpolation needed for a bare reference — var.instance_type evaluates to the string. The resource below reads both variables, building a name from the environment and selecting the instance type from the input.
resource "aws_instance" "app" { ami = "ami-0abc123" instance_type = var.instance_type tags = { Name = "app-${var.environment}" Environment = var.environment } }
Where Values Come From
Terraform collects a variable's value from several sources and the most specific wins. In ascending order of precedence: the default in the block, then terraform.tfvars, then any *.auto.tfvars files (alphabetical), then -var-file and -var flags on the command line. The TF_VAR_ environment variables sit below the tfvars files. Knowing this order is what lets you predict which value actually applies.
# prod.tfvars instance_type = "m5.large" environment = "prod" # an environment variable feeds var.environment export TF_VAR_environment=staging # a -var flag overrides the tfvars file terraform apply -var-file=prod.tfvars -var="instance_type=m5.xlarge"
Required Variables and Automation
A variable with no default is required. In an interactive session Terraform prompts for it; in automation there is no human to answer, so an unset required variable either hangs waiting for input or fails the run. That is why CI pipelines always supply every required variable through a -var-file or TF_VAR_ environment variable, never relying on the prompt.
Per-Environment Variable Files
The same code drives dev and prod by swapping the variable file: terraform apply -var-file=dev.tfvars versus -var-file=prod.tfvars. The configuration stays byte-for-byte identical across environments, and the only thing that differs is the inputs — which is exactly the property that makes a config reusable rather than copy-pasted per environment.
Sensitive Variables
Setting sensitive = true on a variable keeps its value out of plan and apply output, so a password passed in does not get echoed into a terminal or a CI log. It does not encrypt anything and it does not keep the value out of state — if the value flows into a resource attribute, it lands in the state file in plaintext regardless. sensitive is about display, not storage.
- Relying on the interactive prompt for a required variable in CI, where no human answers and the run hangs until it times out or fails.
- Misreading precedence and being surprised a
-varflag overrides the.tfvarsfile — the more specific command-line source always wins. - Committing a
terraform.tfvarsfull of one environment's specifics, coupling code that should be reusable to a single environment. - Putting a secret in a variable
defaultin code, so it sits in version control in plaintext regardless ofsensitive = true. - Leaving a stray
*.auto.tfvarsin the directory, which Terraform loads automatically and silently overrides what you thought you set.
- Give every variable a
descriptionand an explicittype— the description is the interface documentation a caller reads. - Drive environments with
-var-file=prod.tfvars, keeping the configuration identical across every environment. - Pass secrets through
TF_VAR_environment variables or a secrets manager, never as a committeddefault. - Set a
defaultonly for values that are genuinely environment-independent, so a wrong environment can't inherit a stale fallback. - Mark any secret variable
sensitive = trueto keep it out of plan output and CI logs, while still securing state separately.
Knowledge Check
Both a -var flag and a terraform.tfvars file set instance_type. Which value applies?
- The
-varflag, because the command line is the most specific source and wins - The
terraform.tfvarsvalue, because a file is more authoritative than a flag - Neither — Terraform errors on the conflict and refuses to plan
- Whichever was defined first in alphabetical order of the source name
What makes a variable required rather than optional?
- Declaring it with no
default, so Terraform must obtain a value from somewhere - Adding the
required = trueargument to the variable block declaration - Marking the variable with
sensitive = truein its block - Referencing the variable from at least one resource somewhere in the configuration
What does sensitive = true on a variable actually do?
- Suppresses the value in plan and apply output; it does not encrypt it or keep it out of state
- Encrypts the value at rest in the state file using the backend's key
- Prevents the value from ever being written into the state file at all
- Forces the value to be supplied through an environment variable only, never through a tfvars file
Why pass a database password via TF_VAR_db_password instead of a variable default?
- A
defaultin code lands in version control in plaintext; an environment variable keeps the secret out of the committed config - Environment variables holding secrets are encrypted by Terraform automatically before they are read in and used during a plan
- A variable
defaultcannot hold a string value longer than 64 characters - Only values supplied via environment variables can be marked
sensitive
You got correct