OpenTofu: A Beginners Guide to a Terraform Fork Including Migration From Terraform

OpenTofu Basics

Using Input Variables

Replacing hardcoded values with input variables in OpenTofu (a drop-in replacement for Terraform) makes your infrastructure code more modular, configurable, and reusable. In this guide, you’ll learn how to:

  • Define variables in a dedicated file
  • Reference them in resource blocks
  • Override defaults at runtime
  • Understand OpenTofu’s variable precedence

This approach applies to any provider—from local files to AWS EC2 instances—so you can eliminate literal strings and numbers scattered across your configuration.


Table of Contents


Defining Variables

Best practice is to keep all variable definitions in variables.tf (you can also place them alongside resources in main.tf, but separation improves readability).

// variables.tf
variable "filename" {
  description = "Path to the output file"
  default     = "/root/pets.txt"
}

variable "content" {
  description = "Text content written into the file"
  default     = "We love pets!"
}

variable "prefix" {
  description = "Prefix for random pet names"
  default     = "Mrs"
}

variable "separator" {
  description = "Separator between prefix and pet name"
  default     = "."
}

variable "length" {
  description = "Length of the random suffix"
  default     = "1"
}

Each block names the variable and can include:

  • description (optional): clarifies its purpose
  • default: used when no other value is supplied
  • type (optional): for stricter validation (e.g., string, number, list(string))

Avoid Hardcoded Secrets

Do not store sensitive credentials (like passwords or API keys) in default. Use environment variables, a secure vault provider, or encrypted files instead.


Referencing Variables

In your main.tf, replace literal values with var.<name> references:

resource "local_file" "pet" {
  filename = var.filename
  content  = var.content
}

resource "random_pet" "my-pet" {
  prefix    = var.prefix
  separator = var.separator
  length    = var.length
}

Note

When referencing variables, do not wrap var.name in quotes.
Correct: filename = var.filename
Incorrect: filename = "var.filename"

Apply these changes:

$ tofu apply

If you need different defaults, edit variables.tf (for example, set length = "2") and re-run tofu apply.


Example: AWS EC2 Instance

Use variables to configure cloud resources just as easily:

// main.tf
resource "aws_instance" "webserver" {
  ami           = var.ami
  instance_type = var.instance_type
}

// variables.tf
variable "ami" {
  description = "AMI ID for the EC2 instance"
  default     = "ami-0edab43b6fa892279"
}

variable "instance_type" {
  description = "EC2 instance type"
  default     = "t2.micro"
}

You can still override these at apply time without changing the file.


Overriding Variable Values

OpenTofu supports four primary ways to supply or override variable values:

MethodDescriptionExample
Prompted InputLeave out default and answer interactive prompthcl\nvariable "ami" {}\nvariable "instance_type" {}\n<br/>$ tofu apply
CLI FlagsPass -var flags on the command linebash\n$ tofu apply \\\n -var "ami=ami-0edab43b6fa892279" \\\n -var "instance_type=t2.micro"\n
Environment VariablesSet TF_VAR_<name> in your shellbash\nexport TF_VAR_ami="ami-0edab43b6fa892279"\nexport TF_VAR_instance_type="t2.micro"\n$ tofu apply\n
tfvars FilesUse .tfvars or .tfvars.json filesvariables.tfvars:<br/>hcl\nami = "ami-0edab43b6fa892279"\ninstance_type = "t2.micro"\n<br/>$ tofu apply -var-file=variables.tfvars

Variable Precedence

When the same variable is defined multiple times, OpenTofu applies them in this order (lowest → highest):

  1. Environment variables (TF_VAR_name)
  2. terraform.tfvars
  3. .auto.tfvars / .auto.tfvars.json (alphabetical)
  4. -var-file
  5. -var flags

Example scenario:

export TF_VAR_type="t2.nano"          # (1)
# terraform.tfvars: type = "t3.micro"  # (2)
# vars.auto.tfvars: type = "t3.small"  # (3)
$ tofu apply -var "type=t2.medium"     # (5)

The final instance_type will be t2.medium, since -var overrides all others.


Watch Video

Watch video content

Previous
Demo Multiple Providers