default is provided, you must supply a value at runtime (via CLI flags like -var, environment variables, or tfvars files). Within a variable block you can include:
default— a default value used when no other value is provideddescription— a helpful human-readable explanation (recommended)type— constrains accepted values (e.g.,string,list(string),object({...}))sensitive— iftrue, hides the value in CLI plan/apply output
Setting sensitive = true suppresses the value in plan/apply output, but the value will still be recorded in the OpenTofu state file. Protect state (for example, by enabling encryption and restricting access) to keep secrets safe.
Validation rules for variables
You can add avalidation block inside a variable to enforce constraints and return helpful error messages. For example, AWS AMI IDs typically start with ami-. The following variable enforces that rule and provides a custom error message.
Basic scalar types
OpenTofu supports these basic HCL scalar types:string, number, and bool (HCL uses bool rather than the word “boolean”). If you omit type, it defaults to any.
If
type is omitted, the variable’s type is any by default—using explicit types is recommended to catch configuration errors early.number and bool:
Type coercion and mismatches
- If you provide both
typeanddefault, the default must match the declared type. - OpenTofu will attempt some conversions (for example, string ↔ number or string ↔ bool), but relying on coercion is error-prone.
- If coercion is impossible (for example,
type = boolwithdefault = 1), OpenTofu will error and you must fix the mismatch.
Collections and complex types
Beyond scalars, OpenTofu supports:list, set, map, object, and tuple. Use typed constructors such as list(string) or map(number) to enforce element types.
Type reference table:
| HCL Type | Use Case | Example |
|---|---|---|
| string | Simple text values | "/root/pets.txt" |
| number | Numeric values | 1 |
| bool | true/false flags | true |
| any | Accept any type (default when omitted) | default = "value" |
| list | Ordered sequence | ["web1", "web2"] |
| set | Unordered unique collection | ["db1","db2"] |
| map | Key-value lookup | { region1 = "us-east-1" } |
| object | Structured named attributes with types | object({ name=string, age=number }) |
| tuple | Fixed-length sequence with heterogeneous types | tuple([string, number]) |
Lists
Alist is an ordered sequence (index starts at 0). Use list(string) (or list(number), etc.) to constrain element types.
Maps
Amap is a key-value collection. Use map(string) or map(number) to constrain value types.
Combining types with constraints
You can declare lists of specific types or maps of numbers. If values don’t match the declared constraint and cannot be coerced, OpenTofu will fail.Sets
Aset is an unordered collection that forbids duplicates. Use set(string) or set(number).
Valid set example:
Objects
Objects model structured data with named attributes and specific types.Tuples
Atuple is a fixed-length sequence where each element can have a different type. The default must match the exact length and element types.
Summary and best practices
- Use
default,description,type, andsensitiveinside variable blocks to make configurations self-documenting and safer. - Prefer explicit
typedeclarations to catch type errors early during plan/evaluation. - Add
validationblocks to enforce format rules and provide actionable error messages. - Understand basic scalar types (
string,number,bool) and collection/complex types (list,set,map,object,tuple). - Avoid relying on automatic type coercion — specify matching types or convert values explicitly.
- Protect sensitive values stored in state (consider remote state backends with encryption and strict access controls).
- OpenTofu Documentation
- HCL type information (HashiCorp) — see HCL and Terraform docs for additional examples
- Best practices for secrets and state file security: use encrypted remote backends and access controls