2.04 Terraform Input Variables
Overview
Input variables allow Terraform configurations to be parameterised — separating values from resource logic so the same code can be reused across environments without modifying main.tf.
Abstract
Hardcoding argument values directly in resource blocks reduces reusability and makes configs brittle. Input variables declared in variables.tf decouple values from logic, enabling the same configuration to deploy different resources simply by changing variable values — without touching the resource definitions.
Why It Matters in Production
- Reuse the same Terraform modules across dev, staging, and production by passing different variable values
- Keep
main.tfstable and reviewable — onlyvariables.tfor.tfvarsfiles change between deployments - Enables CI/CD pipelines to inject environment-specific values at runtime without modifying source code
- Prevents accidental hardcoded secrets and environment-specific values from leaking into shared configs
Key Concepts
| Concept | Description |
|---|---|
| Input variable | A parameterised value declared with the variable block |
default |
Optional fallback value used when no value is explicitly passed |
var.<name> |
Syntax to reference a variable inside a resource block |
variables.tf |
Convention file where all variable declarations are stored |
| Hardcoded value | A literal value written directly in a resource argument — avoid in production |
Variable Block Syntax
- The
variablekeyword is required - The name should match the argument it represents (e.g.
filename,content) defaultis optional but is the simplest way to assign a value- No quotes around
var.<name>references in resource blocks
Example Configuration & Commands
Before — hardcoded values in main.tf
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "We love pets!"
}
resource "random_pet" "my-pet" {
prefix = "Mrs"
separator = "."
length = "1"
}
After — values moved to variables.tf
Applying the configuration
Updating values without touching main.tf
To change the file content and pet name length, update only variables.tf:
variable "content" {
default = "My favorite pet is Mrs. Whiskers"
}
variable "length" {
default = "2"
}
Then re-apply:
Note
Changing content or length forces Terraform to destroy and recreate the affected resources. The plan will show -/+ (destroy then create) for those resources.
apply output — forced replacement example
-/+ resource "local_file" "pet" {
~ content = "We love pets!" -> "My favorite pet is Mrs. Whiskers" # forces replacement
filename = "/root/pet.txt"
}
-/+ resource "random_pet" "my-pet" {
~ id = "Mrs.Hen" -> (known after apply)
~ length = 1 -> 2 # forces replacement
prefix = "Mrs"
separator = "."
}
Plan: 2 to add, 0 to change, 2 to destroy.
AWS EC2 example with variables
Variable Block — Full Syntax
A variable block supports additional optional meta-arguments beyond default:
variable "instance_type" {
description = "EC2 instance type to deploy"
type = string
default = "t2.micro"
sensitive = false
}
| Meta-argument | Description |
|---|---|
description |
Human-readable explanation of the variable's purpose |
type |
Enforces a type constraint: string, number, bool, list, map, object |
default |
Fallback value when none is provided |
sensitive |
Hides the value from plan/apply output and state logs |
Best Practices
Best Practices
- Always declare variables in a dedicated
variables.tffile — keep resource logic inmain.tfseparate from values. - Add a
descriptionto every variable so collaborators and module users understand its purpose. - Add a
typeconstraint to catch misconfigured inputs early, beforeapply. - Use
sensitive = truefor passwords, tokens, and private keys — this prevents the value from appearing in logs. - Use
.tfvarsfiles (e.g.dev.tfvars,prod.tfvars) to manage environment-specific values rather than changingdefaultvalues per environment. - Never store
.tfvarsfiles with secrets in version control — add them to.gitignore.
Security Best Practices
Security
- Mark sensitive variables (
password,token,secret_key) withsensitive = true— Terraform will redact them in plan and apply output. - Do not use
defaultfor secrets — inject them via environment variables (TF_VAR_<name>) or a secrets manager at runtime. - Avoid committing
terraform.tfvarsfiles containing real credentials — use CI secret injection or Vault instead. - Sensitive values still appear in state — ensure remote state backends have encryption at rest enabled.
Do and Don't
| ✅ Do | ❌ Don't |
|---|---|
Declare all variables in variables.tf |
Hardcode environment-specific values directly in main.tf |
Use var.<name> (no quotes) to reference variables |
Wrap var.<name> in quotes — it will be treated as a literal string |
Add description and type to every variable |
Leave variables undocumented and untyped in shared modules |
Use sensitive = true for secrets |
Log or output sensitive variable values in plaintext |
Use .tfvars files for per-environment overrides |
Change default values in variables.tf to switch environments |
Common Mistakes
Common Mistakes
- Quoting variable references: Writing
filename = "var.filename"treats it as a literal string. The correct form isfilename = var.filename(no quotes). - Not expecting forced replacement: Changing a variable value used in an immutable argument (like
contentinlocal_file) will destroy and recreate the resource, not update it in place. - Missing
defaultwith no other value source: Ifdefaultis omitted and no.tfvarsor-varflag is provided, Terraform prompts interactively — which blocks CI pipelines. - Reusing the same variable name for different resources: Variable names are global within a configuration directory — name collisions cause unexpected value sharing.
Troubleshooting
# Check what value a variable resolves to in the current config
terraform console
> var.filename
# Pass a variable value directly on the command line (overrides default)
terraform apply -var="length=3"
# Pass all variables from a file
terraform apply -var-file="prod.tfvars"
# Set a variable via environment variable (useful in CI)
export TF_VAR_length=3
terraform apply
# Validate the configuration (catches type mismatches and missing variables)
terraform validate
Quick Recap
- Variables remove hardcoded values from resource blocks, making configs reusable and environment-agnostic
- Declare variables in
variables.tfusing thevariableblock; reference them withvar.<name>(no quotes) defaultprovides a fallback value; variables without a default require a value at runtime- Changing a variable value may force resource replacement depending on which argument it affects
- Use
sensitive = true,.tfvarsfiles, andTF_VAR_environment variables for production-grade variable management
Keeping Variable Values Out of GitHub
Committing real values (passwords, tokens, paths, AMI IDs) inside variables.tf exposes them in version control history. Use the following pattern to keep declarations public and values private.
Pattern — separate declarations from values
Add to .gitignore:
Inject values in CI/CD (GitHub Actions)
Store secrets in GitHub → Settings → Secrets and variables → Actions, then reference them in your workflow:
Terraform automatically picks up any environment variable prefixed with TF_VAR_.
What to commit vs what to ignore
| File | Commit to Git? | Reason |
|---|---|---|
variables.tf (no defaults) |
✅ Yes | Contains only shape/type — no values |
terraform.tfvars |
❌ No | Contains real values — gitignore it |
*.auto.tfvars |
❌ No | Auto-loaded by Terraform — same risk |
.terraform.lock.hcl |
✅ Yes | Pins provider versions — safe and recommended |
*.tfstate / *.tfstate.backup |
❌ Never | Contains all resource attributes in plaintext |
Tip
For sensitive values like passwords and API keys, skip tfvars entirely and inject via TF_VAR_ environment variables from your CI secret store or HashiCorp Vault. Nothing sensitive ever touches disk.
Interview / Revision Notes
Revision
- Why use input variables instead of hardcoded values? They enable code reuse across environments and separate configuration logic from values.
- What syntax references a variable in a resource block?
var.<variable_name>— no quotes. - What file conventionally holds variable declarations?
variables.tf. - What happens if a variable has no
defaultand no value is provided? Terraform prompts interactively, or errors in non-interactive (CI) environments. - How do you pass a variable value without editing any
.tffile? Use-var="name=value", a-var-file, orTF_VAR_<name>environment variable. - Does changing a variable always update resources in place? No — some argument changes force destroy-and-recreate (shown as
-/+in the plan).