0
0
TerraformHow-ToBeginner · 4 min read

How to Use Provisioner in Terraform: Syntax and Examples

In Terraform, a provisioner runs scripts or commands on a resource after it is created or before it is destroyed. You add a provisioner block inside a resource block to specify actions like running shell commands or copying files.
📐

Syntax

A provisioner block is placed inside a resource block. It has a type like local-exec or remote-exec and contains configuration for the commands or scripts to run.

  • local-exec: Runs commands on the machine running Terraform.
  • remote-exec: Runs commands on the remote resource via SSH or WinRM.
  • when: Optional, controls if provisioner runs create or destroy.
terraform
resource "aws_instance" "example" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  provisioner "local-exec" {
    command = "echo Hello from Terraform"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx"
    ]

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host        = self.public_ip
    }
  }
}
💻

Example

This example creates an AWS EC2 instance and uses a remote-exec provisioner to install Nginx on it after creation. It connects via SSH using the instance's public IP.

terraform
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"  # Ubuntu Server 20.04 LTS
  instance_type = "t2.micro"

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx"
    ]

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host        = self.public_ip
    }
  }
}
Output
Terraform will create the EC2 instance, then connect via SSH and run the commands to update packages and install Nginx.
⚠️

Common Pitfalls

  • Provisioners run only after resource creation; they do not run on updates unless the resource is replaced.
  • Using provisioners for configuration management is discouraged; use dedicated tools like Ansible or cloud-init instead.
  • Incorrect connection settings cause remote-exec to fail.
  • Provisioners can cause Terraform runs to hang if commands do not finish or fail silently.
terraform
resource "aws_instance" "bad_example" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  provisioner "remote-exec" {
    inline = ["sudo apt-get update"]

    connection {
      type = "ssh"
      user = "wrong-user"  # Incorrect user causes failure
      host = self.public_ip
    }
  }
}

# Corrected connection block
resource "aws_instance" "good_example" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  provisioner "remote-exec" {
    inline = ["sudo apt-get update"]

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/id_rsa")
      host        = self.public_ip
    }
  }
}
📊

Quick Reference

Use local-exec to run commands on your local machine and remote-exec to run commands on the created resource. Always configure the connection block correctly for remote commands. Avoid using provisioners for complex setup; prefer dedicated configuration tools.

Provisioner TypeDescriptionTypical Use Case
local-execRuns commands on the machine running TerraformRun local scripts or commands after resource creation
remote-execRuns commands on the remote resource via SSH or WinRMInstall software or configure remote servers
fileCopies files to remote machinesTransfer configuration files or scripts

Key Takeaways

Add provisioner blocks inside resource blocks to run scripts or commands after resource creation.
Use local-exec for local commands and remote-exec for commands on remote resources via SSH or WinRM.
Always configure connection details correctly for remote-exec to work.
Provisioners should be a last resort; prefer configuration management tools for complex setups.
Provisioners run only on resource creation or destruction, not on updates.