Suppose an instance needs a command Terraform cannot express through its resource configuration. A provisioner can run a command or create files locally or on another machine when Terraform creates or destroys a resource. Use one only when a better option is unavailable: provisioners add failure points, deployment time, and behavior that can be difficult to debug. section 10.3
Choose where the command runs:
- remote-exec runs on another machine and requires a connection. Use inline commands, one script, or an ordered list of scripts; each provisioner block selects only one form. section 10.3.2
- local-exec runs where Terraform runs, needs no connection, and accepts a command that can itself launch a script. section 10.3.2
Configure an instance over SSH
An aws_instance can use a connection block with type = "ssh", user = "ubuntu", and host = self.public_ip. Its remote-exec provisioner can then install nginx with inline commands or upload and run a script. A resource-level connection applies to its provisioners; a provisioner can instead define its own. Keep private SSH keys out of committed code. section 10.3.1 section 10.3.2
Listing 10.13 The remote-exec provisioner
resource "aws_instance" "main" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}
provisioner "remote-exec" { #1
inline = [ #2
"sudo apt-get update",
"sudo apt-get install -y nginx"
]
}
provisioner "remote-exec" { #3
script = "${path.module}/scripts/install.sh" #4
}
provisioner "remote-exec" {
scripts = [ #5
"${path.module}/scripts/install.sh",
"${path.module}/scripts/configure.sh"
]
}
}
Compare the three remote-exec command forms on an instance with an SSH connection. section 10.3.2
Provisioners run at creation by default. Set when = destroy for cleanup during destruction or replacement, but removing the resource block also removes that instruction. A failure normally stops apply and taints the resource for replacement on the next plan; on_failure = continue ignores the error instead. section 10.3.4
Use terraform_data when a provisioner should not belong to a particular infrastructure resource. Its depends_on can wait for several resources; triggers_replace can cause the provisioner to run again when selected values change. Older configurations may use null_resource for this role. section 10.3.5 section 6.8.4
Prefer prebuilt machine images for software installation and Cloud-Init for launch-time configuration or files. For machine metadata, consider output variables or the local provider. Provisioners cannot load external data into resources; the external provider serves that different need. section 10.3.6 section 10.4
