Templatefile Function: Separating Logic from Configuration

Learn how Terraform’s templatefile() cleanly separates logic from HCL configs, enabling reusable, readable modules.

The templatefile function is powerful but can be confusing to use correctly.

The Problem

# Mixing logic and configuration
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  user_data = <<-EOT
    #!/bin/bash
    echo "Hello, ${var.environment}!"
    %{for port in var.open_ports}
    firewall-cmd --permanent --add-port=${port}/tcp
    %{endfor}
    firewall-cmd --reload
  EOT
}

The Solution

# Using templatefile (templates/user_data.tftpl)
# #!/bin/bash
# echo "Hello, ${environment}!"
# %{for port in open_ports}
# firewall-cmd --permanent --add-port=${port}/tcp
# %{endfor}
# firewall-cmd --reload

# In your Terraform code:
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  user_data = templatefile("${path.module}/templates/user_data.tftpl", {
    environment = var.environment
    open_ports  = var.open_ports
  })
}

Separating templates makes your configuration cleaner and more maintainable. Scalr provides visibility into these template renderings during the plan stage to help catch issues early.