Terraform Configuration Syntax
Terraform configurations are written in HCL (HashiCorp Configuration Language), which is designed to be both human-readable and machine-parseable. This page covers the detailed syntax rules.
File Extensions
Terraform supports two file formats:
.tf - Native HCL syntax (recommended)
.tf.json - JSON syntax for machine generation
This documentation focuses on the native HCL syntax, which is the standard format for human-authored configurations.
Basic Syntax
Blocks
Blocks are the primary structural element. A block has a type, optional labels, and a body:
< BLOCK_TYPE > "<LABEL>" "<LABEL>" {
# Block body
< ARGUMENT > = < EXPRESSION >
< NESTED_BLOCK > {
# Nested block body
}
}
Example
resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "t2.micro"
network_interface {
device_index = 0
description = "Main network interface"
}
}
In this example:
resource is the block type
"aws_instance" and "web" are labels
ami and instance_type are arguments
network_interface is a nested block
Arguments
Arguments assign values within blocks:
< IDENTIFIER > = < EXPRESSION >
The identifier must be a valid variable name (letters, digits, underscores, and hyphens).
Identifiers
Valid identifiers:
Start with a letter or underscore
Contain letters, digits, underscores, and hyphens
Are case-sensitive
variable "instance_type" { } # Valid
variable "instance-type" { } # Valid
variable "_private" { } # Valid
variable "2nd_instance" { } # Invalid - starts with digit
While hyphens are allowed in identifiers, underscores are preferred for consistency with most programming languages.
Expressions
Expressions produce values and can be:
Literal Values
# String
name = "example"
# Number
count = 3
pi = 3.14159
# Boolean
enabled = true
disabled = false
# Null
default_value = null
Collections
# List/tuple
az_list = [ "us-west-2a" , "us-west-2b" , "us-west-2c" ]
# Map/object
tags = {
Name = "example"
Environment = "production"
}
References
Reference other values in the configuration:
# Resource attribute
ami = aws_ami . ubuntu . id
# Variable
instance_type = var . instance_type
# Local value
subnet_id = local . primary_subnet
# Data source
vpc_id = data . aws_vpc . main . id
Operators
Terraform supports standard operators:
# Arithmetic
result = 2 + 3 # 5
result = 10 - 4 # 6
result = 3 * 4 # 12
result = 10 / 2 # 5
result = 10 % 3 # 1
# Comparison
equal = 5 == 5 # true
not_equal = 5 != 3 # true
greater = 5 > 3 # true
greater_or_equal = 5 >= 5 # true
# Logical
and_op = true && false # false
or_op = true || false # true
not_op = ! false # true
Conditional Expressions
instance_type = var . environment == "production" ? "t2.large" : "t2.micro"
For Expressions
Transform collections:
# List transformation
uppercase_names = [ for name in var . names : upper (name)]
# Map transformation
port_map = { for k , v in var . ports : k => v + 1000 }
# Filtering
production_instances = [ for i in var . instances : i if i . environment == "production" ]
Splat Expressions
Shorthand for extracting attributes:
# Extract all IDs
instance_ids = aws_instance . web [ * ] . id
# Works with resources created with count
private_ips = aws_instance . web [ * ] . private_ip
String Templates
Interpolation
Embed expressions in strings:
greeting = "Hello, ${ var . name } !"
path = "/var/lib/ ${ var . service } /data"
Directives
Control whitespace and flow:
# For loop
user_names = << EOT
%{ for name in var . users ~ }
- ${ name }
%{ endfor ~ }
EOT
# Conditional
config = << EOT
%{ if var . debug_mode ~ }
debug = true
%{ else ~ }
debug = false
%{ endif ~ }
EOT
Heredoc Syntax
Multi-line strings:
user_data = <<- EOT
#!/bin/bash
echo "Hello World"
apt-get update
apt-get install -y nginx
EOT
Three comment styles:
# Single-line comment (preferred)
// Alternative single-line comment
/*
Multi-line comment
Useful for larger blocks
*/
Special Characters
Escaping
Escape special characters in strings:
message = "Quote: \" Hello \" and newline: \n "
path = "C: \\ Users \\ Admin"
template = "$${not_interpolated}"
Unicode
Unicode characters are supported:
variable "π" {
default = 3.14159265359
}
output "emoji" {
value = "🚀"
}
Style Conventions
Use 2 spaces for indentation (not tabs): resource "aws_instance" "example" {
ami = "ami-12345678"
network_interface {
device_index = 0
}
}
Align values for better readability: resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "t2.micro"
subnet_id = var . subnet_id
}
Use blank lines to separate logical sections: variable "region" {
type = string
}
variable "instance_type" {
type = string
}
Terraform includes a formatter:
# Format current directory
terraform fmt
# Format specific file
terraform fmt main.tf
# Check if files are formatted
terraform fmt -check
JSON Syntax
For machine-generated configurations:
{
"resource" : {
"aws_instance" : {
"web" : {
"ami" : "ami-12345678" ,
"instance_type" : "t2.micro"
}
}
}
}
The JSON syntax is functionally equivalent to HCL but is less human-friendly. Use it only when generating configurations programmatically.
Validation
The parser validates syntax according to the HCL specification. Common errors include:
Missing closing braces
Invalid identifier names
Incorrect expression syntax
Mismatched quotes
Use terraform validate to check for syntax errors:
Next Steps
Expressions Learn about expression syntax in detail
Functions Explore built-in functions