Terraform Syntax Reference

Comprehensive reference for terraform syntax reference covering essential concepts, practical examples, and production best practices.

Terraform syntax defines how infrastructure is declared, composed, and managed as code. Use this reference when writing, debugging, or reviewing .tf files—whether crafting a single resource block or orchestrating multi-environment deployments. The syntax is explicit, declarative, and idempotent: a Terraform configuration file is the source of truth for your entire cloud stack.

Resource Blocks

Define infrastructure components with resource blocks. The block’s type, name, and configuration keys are precise and tightly coupled.

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web.id]

  tags = {
    Name = "web-server"
    Environment = "production"
  }

  user_data = <<EOF
#!/bin/bash
echo "Hello from Terraform"
EOF
}

Resource Block Best Practices

  resource "aws_instance" "app" {
    count = 3

    ami           = "ami-12345678"
    instance_type = "t3.small"
    tags = {
      Name = "app-server-${count.index}"
    }
  }
  resource "aws_s3_bucket" "logs" {
    for_each = {
      staging = "staging-logs"
      production = "prod-logs"
    }

    bucket = each.value
    tags = {
      Environment = each.key
    }
  }
  resource "aws_s3_bucket" "data" {
    bucket = "my-data-bucket"

    depends_on = [
      aws_lambda_function.processor,
      aws_iam_role.data_processor
    ]
  }

Data Sources

Fetch values from external systems during configuration evaluation.

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

Common Pitfalls

  data "aws_ami" "app_images" {
    for_each = {
      staging = "ami-111111"
      prod    = "ami-222222"
    }

    most_recent = true
    owners      = ["123456789012"]

    filter {
      name   = "name"
      values = [each.key == "staging" ? "app-staging-*" : "app-prod-*"]
    }
  }

Variables and Outputs

Define inputs and outputs with variable and output blocks.

variable "region" {
  description = "AWS region for deployment"
  type        = string
  default     = "us-east-1"
}

variable "instance_types" {
  type = map(string)
  default = {
    web   = "t3.small"
    db    = "r5.large"
    worker = "m5.xlarge"
  }
}

output "public_ip" {
  value = aws_instance.web.public_ip
  description = "Public IP of the web server"
  sensitive = true
}

Variable Type Rules

  variable "app_config" {
    type = object({
      name    = string
      version = string
      env     = string
      tags    = map(string)
    })
    default = {
      name    = "my-app"
      version = "1.0"
      env     = "prod"
      tags    = { Team = "backend" }
    }
  }

Modules

Encapsulate reusable configurations with module blocks.

module "vpc" {
  source  = "./modules/vpc"
  version = "1.2.0"

  cidr_block = "10.0.0.0/16"
  azs        = ["us-east-1a", "us-east-1b"]
  public_subnets = {
    "us-east-1a" = "10.0.1.0/24"
    "us-east-1b" = "10.0.2.0/24"
  }
}

Module Best Practices

  module "database" {
    source  = "git::https://github.com/example/terraform-modules.git//db"
    version = "v1.5.0"
  }
  module "frontend" {
    source = "./modules/frontend"

    app_config = {
      name = "frontend"
      env  = "staging"
    }

    module "backend" {
      source = "./modules/backend"
      db_url = module.database.db_url
    }
  }

Providers

Configure provider-specific settings.

provider "aws" {
  region  = "us-west-2"
  profile = "production"
  shared_credentials_file = "/home/ubuntu/.aws/credentials"
  default_tags = {
    Environment = "staging"
    Team        = "devops"
  }
}

Provider Scope Rules

  module "web" {
    source = "./modules/web"

    provider "aws" {
      region = "us-east-1"
      default_tags = {
        Environment = "production"
      }
    }
  }
  provider "aws" {
    version = "~> 4.0"
  }

Terraform Core Configuration

Set global settings in terraform block.

terraform {
  required_version = ">= 1.4.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
    docker = {
      source  = "kreuzwerker/docker"
      version = ">= 2.0.0"
    }
  }
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "dev/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
  }
}

Backend Configuration Gotchas

  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/${local.env}/terraform.tfstate"
    region = "us-east-1"
  }

Expressions and Interpolation

Terraform uses a rich expression language.

locals {
  db_name = "myapp-${var.environment}"
  instance_count = length(var.instance_types)
}

resource "aws_rds_instance" "db" {
  identifier  = local.db_name
  instance_type = var.instance_types["db"]
  allocated_storage = 20

  parameter_group_name = aws_db_parameter_group.custom.name
}

Interpolation Syntax

  tags = {
    Name = "web-${var.environment}"
  }

Error Messages and Failure Modes

Terraform syntax is precise and expressive. When it fails, the error messages are exact, and the configuration structure guides you directly to the source of the problem.

This page was rewritten on 10 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.