BudiBadu Logo
Samplebadu

Terraform by Example: Provisioners

1.x

Provisioners execute scripts during resource creation. This sample code shows `local-exec` and `remote-exec`, but remember they should be a last resort.

Code

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"
  key_name      = "my-key"

  # Execute command on the machine running Terraform
  provisioner "local-exec" {
    command = "echo ${self.private_ip} >> private_ips.txt"
  }

  # Execute command on the remote resource
  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx",
      "sudo systemctl start nginx"
    ]

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = file("~/.ssh/my-key.pem")
      host        = self.public_ip
    }
  }
}

Explanation

Provisioners allow you to execute scripts on a local or remote machine as part of the resource creation or destruction process. The local-exec provisioner runs commands on the machine executing Terraform, while remote-exec connects to the resource (usually via SSH) to run commands. They are often used for bootstrapping or initial configuration.

However, HashiCorp explicitly recommends using provisioners only as a last resort. They introduce imperative logic into a declarative tool, break idempotency, and can be difficult to debug. If a provisioner fails, the resource is marked as "tainted" and must be recreated, which can lead to data loss or downtime.

Instead of provisioners, prefer using more robust alternatives:

  • Packer: Create pre-configured machine images (AMIs)
  • Cloud-init: Use standard initialization scripts (e.g., AWS User Data)
  • Ansible/Chef: Use dedicated configuration management tools

Code Breakdown

7
local-exec runs on your computer, not the server.
12
remote-exec runs commands on the newly created instance via SSH.
13-17
inline passes a list of shell commands to execute.
19
connection block defines how Terraform connects to the server (SSH/WinRM).
22
private_key reads the SSH key file for authentication.
23
host = self.public_ip uses the resource's own IP address for the connection.