Terraform Provisioners can be used to do specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure resources.
Provisioners can be used to execute/copy local script or remote script and pass data/file/script to instances at the time of their creation such that the data is immediately available on system boot. such as Amazon EC2: user_data or user_data_base64 on aws_instance, aws_launch_template, and aws_launch_configuration is doing similar work.
local-exec Provisioner
The local-exec provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource.
Example of local-exec Provisioner
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo ${aws_instance.web.private_ip} >> private_ips.txt"
}
}Code language: PHP (php)
The following arguments are supported:
command – (Required) This is the command to execute. It can be provided as a relative path to the current working directory or as an absolute path. It is evaluated in a shell, and can use environment variables or Terraform variables.
working_dir – (Optional) If provided, specifies the working directory where command will be executed. It can be provided as as a relative path to the current working directory or as an absolute path. The directory must exist.
interpreter – (Optional) If provided, this is a list of interpreter arguments used to execute the command. The first argument is the interpreter itself. It can be provided as a relative path to the current working directory or as an absolute path. The remaining arguments are appended prior to the command. This allows building command lines of the form “/bin/bash”, “-c”, “echo foo”. If interpreter is unspecified, sensible defaults will be chosen based on the system OS.
environment – (Optional) block of key value pairs representing the environment of the executed command. inherits the current process environment.
Example of multiple local-exec Provisioners:
resource "aws_instance" "web" {
ami = "ami-5b673c34"
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
}
provisioner "local-exec" {
command = "echo 'Welcome to Terraform Allianz Classx' >> /Users/rajeshkumar/terraform/local-exec.txt"
}
provisioner "local-exec" {
command = "/bin/bash deploy.sh"
}
provisioner "local-exec" {
command = "open WFH, '>completed.txt' and print WFH scalar localtime"
interpreter = ["perl", "-e"]
}
}Code language: JavaScript (javascript)
Creation-Time Provisioners
By default, provisioners run when the resource they are defined within is created. Creation-time provisioners are only run during creation, not during updating or any other lifecycle.
If a creation-time provisioner fails, the resource is marked as tainted. A tainted resource will be planned for destruction and recreation upon the next terraform apply.
Destroy-Time Provisioners
If when = “destroy” is specified, the provisioner will run when the resource it is defined within is destroyed. Destroy provisioners are run before the resource is destroyed. If they fail, Terraform will error and rerun the provisioners again on the next terraform apply.
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
when = "destroy"
command = "echo 'Destroy-time provisioner'"
}
}Code language: PHP (php)
Failure Behavior
By default, provisioners that fail will also cause the Terraform apply itself to fail. The on_failure setting can be used to change this. The allowed values are:
“continue” – Ignore the error and continue with creation or destruction.
“fail” – Raise an error and stop applying (the default behavior). If this is a creation provisioner, taint the resource.
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo The server's IP address is ${self.private_ip}"
on_failure = "continue"
}
}Code language: PHP (php)
Provisioners Without a Resource
If you need to run provisioners that aren’t directly associated with a specific resource, you can associate them with a null_resource.
Instances of null_resource are treated like normal resources, but they don’t do anything. Like with any other resource, you can configure provisioners and connection details on a null_resource.
resource "null_resource" "example1" {
provisioner "local-exec" {
command = "open WFH, '>completed.txt' and print WFH scalar localtime"
interpreter = ["perl", "-e"]
}
}
resource "null_resource" "example2" {
provisioner "local-exec" {
command = "Get-Date > completed.txt"
interpreter = ["PowerShell", "-Command"]
}
}Code language: JavaScript (javascript)
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals