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
- Referencing Variables
- Example: Local File & Random Pet
- Example: AWS EC2 Instance
- Overriding Variable Values
- Variable Precedence
- Links and References
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 purposedefault
: used when no other value is suppliedtype
(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:
Method | Description | Example |
---|---|---|
Prompted Input | Leave out default and answer interactive prompt | hcl\nvariable "ami" {}\nvariable "instance_type" {}\n <br/>$ tofu apply |
CLI Flags | Pass -var flags on the command line | bash\n$ tofu apply \\\n -var "ami=ami-0edab43b6fa892279" \\\n -var "instance_type=t2.micro"\n |
Environment Variables | Set TF_VAR_<name> in your shell | bash\nexport TF_VAR_ami="ami-0edab43b6fa892279"\nexport TF_VAR_instance_type="t2.micro"\n$ tofu apply\n |
tfvars Files | Use .tfvars or .tfvars.json files | variables.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):
- Environment variables (
TF_VAR_name
) - terraform.tfvars
- .auto.tfvars / .auto.tfvars.json (alphabetical)
- -var-file
- -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.
Links and References
Watch Video
Watch video content