Mastering tfvars: A Concise Guide for Terraform and OpenTofu
Learn how to structure, secure & reuse tfvars files to streamline Terraform/OpenTofu deployments across environments—complete syntax, tips & tools.
1. Introduction: The Power of tfvars
tfvars files are essential for parameterizing Infrastructure as Code (IaC) with Terraform and OpenTofu. They allow you to supply input variable values, enabling customization for different environments (dev, prod) or configurations without altering core infrastructure code. This separation promotes reusability, maintainability, and a clear distinction between configuration values and logic. The principles discussed apply to both Terraform and OpenTofu, which is designed as a drop-in replacement.
2. Defining Variables and Assigning Values
- Variable Declaration (
variables.tf): Variables are declared in.tffiles (commonlyvariables.tf) usingvariableblocks. Key arguments include:type: Specifies data type (e.g.,string,number,list,map,object).description: Documents the variable's purpose.default: Provides a default value, making the variable optional.validation: Defines custom rules for the variable's value.sensitive = true: Redacts the value from CLI output (but not from the state file).
- Value Assignment (
.tfvarsfiles):tfvarsfiles assign values to declared variables.- Syntax: HCL (
variable_name = "value") in.tfvarsfiles, or JSON in.tfvars.jsonfiles.
- Syntax: HCL (
Example (terraform.tfvars):
instance_type = "t2.medium"
aws_region = "us-east-1"
3. How Variables are Loaded
Terraform and OpenTofu load variables from tfvars files in specific ways:
- Automatic Loading:
terraform.tfvarsorterraform.tfvars.json: Loaded automatically if present in the root module directory. Used for base/default values for a working copy.*.auto.tfvarsor*.auto.tfvars.json: Any files with these extensions are loaded automatically in lexical (alphabetical) order of their filenames. Useful for segmenting variables or user-specific overrides (often gitignored).
- Explicit Loading (
-var-fileoption):- The
-var-file="custom.tfvars"command-line option explicitly loads a specifiedtfvarsfile. Essential for environment-specific configurations (e.g.,tofu apply -var-file="production.tfvars"). Multiple files can be specified and are loaded in order.
- The
- Scope: Values from
tfvarsfiles apply only to variables declared in the root module.
4. Variable Precedence: The Order of Overrides
If a variable is defined in multiple places, the last one loaded takes precedence. The order (from lowest to highest precedence) for CLI workflows is:
- Environment Variables:
TF_VAR_name(orOPENTOFU_VAR_namefor OpenTofu, which takes precedence if both are set). terraform.tfvarsfile.terraform.tfvars.jsonfile (if both this andterraform.tfvarsexist, JSON usually overrides for the same variable).*.auto.tfvarsor*.auto.tfvars.jsonfiles (loaded alphabetically; later files override earlier ones).- Command-line flags (
-varand-var-file): Processed in the order given; later flags override earlier ones. These have the highest precedence.
Understanding this hierarchy is crucial for debugging.
5. tfvars in Action: Examples
Simple Values (dev.tfvars):
instance_count = 2
enable_monitoring = false
environment_name = "development"
Complex Types (List of Objects in services.tfvars): Assuming variables.tf defines app_services as list(object({ name=string, instance_type=string, port=number })):
// services.tfvars
app_services = [
{ name = "frontend", instance_type = "t3.medium", port = 80 },
{ name = "backend", instance_type = "t3.large", port = 8080 }
]
This is powerful with for_each or count to dynamically create resources.
Environment-Specific Configurations: Use separate files like dev.tfvars and prod.tfvars, loaded via -var-file, to manage different settings (e.g., instance types) for each environment.
6. OpenTofu and tfvars: Key Points
- Compatibility: OpenTofu is largely a drop-in replacement for Terraform, maintaining compatibility with
tfvarshandling (syntax, loading, naming). - Official Documentation: Refer to OpenTofu's official docs for specifics.
- Environment Variables: OpenTofu honors
TF_VAR_for backward compatibility but introducesOPENTOFU_VAR_. If both are set for the same variable,OPENTOFU_VAR_nameprevails. AdoptingOPENTOFU_prefixes is recommended for new OpenTofu projects.
7. Best Practices for tfvars Management
- Multiple Environments:
- Use distinct files for each environment (e.g.,
development.tfvars,production.tfvars). - Load explicitly with
-var-file. - Organize in a dedicated directory (e.g.,
tfvars/orenvironments/).
- Use distinct files for each environment (e.g.,
- Security First: Handling Sensitive Data:
- Golden Rule: Never commit plain-text secrets to version-controlled
tfvarsfiles. - Alternatives:
- Environment Variables: Injected by CI/CD or set locally (use with care).
- Secrets Management Tools: HashiCorp Vault, AWS/Azure/GCP Secret Manager. Fetch secrets at runtime.
- IaC Platforms: Terraform Cloud, Spacelift offer secure variable storage.
- Encryption: Tools like Mozilla SOPS can encrypt values within files.
sensitive = true: Invariables.tf, this redacts values from CLI output but does not encrypt them in the state file. Secure your state file (e.g., remote backend with encryption).
- Golden Rule: Never commit plain-text secrets to version-controlled
- Version Control (
.gitignore):- Commit example
tfvarsfiles (e.g.,terraform.tfvars.example). - Add actual
tfvarsfiles containing secrets or environment-specifics to.gitignore.
- Commit example
- Clarity and Maintainability:
- Use clear naming conventions for files and variables.
- Thoroughly document variables in
variables.tfusingdescription. - Maintain consistency across projects.
8. Advanced Techniques
- Programmatic Generation:
terraform-docs: Can generate templatetfvarsfiles.- Custom Scripts (Shell, Python): Fetch data from external sources (CMDBs, APIs) to build
tfvars.
- CI/CD Integration:
- Store/generate
tfvarssecurely within CI/CD. - Use
-var-fileor environment variables (TF_VAR_/OPENTOFU_VAR_) in pipelines.
- Store/generate
- Workspaces: Use workspace-named
tfvars(e.g.,dev.tfvars) selected dynamically:terraform plan -var-file="${TERRAFORM_WORKSPACE}.tfvars".
9. Troubleshooting Common Pitfalls
- "Undeclared Variable": Variable assigned in
tfvarsbut not declared in.tffiles. Check for typos and ensure declaration. - File Loading/Naming Issues: Incorrect filenames (e.g.,
terraform.tfvar) or location (not in root module). Verify names and paths. - Precedence Misunderstanding: Unexpected values due to overrides from higher-precedence sources. Review the precedence order.
- Syntax Errors: Invalid HCL or JSON in
tfvarsfiles. Validate syntax carefully. - Sensitive Data Exposure: Secrets in version control or state files. Rotate compromised secrets immediately. Implement proper secrets management and
.gitignorerules. - Type Mismatches: Value in
tfvarsdoesn't matchtypeinvariabledeclaration. Ensure values adhere to defined types.
10. Conclusion: Effective Infrastructure Customization
tfvars files are crucial for customizing Terraform and OpenTofu configurations. Mastering their use involves understanding variable declaration, loading mechanisms, precedence, and, critically, security best practices. By avoiding plain-text secrets in version control and adopting robust management strategies, teams can build flexible, secure, and maintainable IaC, enabling efficient management of complex environments.