Terraform
Basics & Fundamentals
- Infrastructure as Code (IaC)
- Declarative Syntax in IaC
- Terraform Configuration Files
- Terraform CLI
- Terraform Init
- Terraform Plan
- Terraform Apply
- Terraform Destroy
Providers & Resources
Variables & Outputs
- Input Variables
- Variable Types
- Default Values
- Environment Variables
- Output Values
- Variable Validation
State Management
- Terraform State File
- Terraform Remote State
- Terraform State Locking
- Terraform Drift Detection
- Terraform Refresh
- Terraform Import
Modules (Reusability)
- Terraform Modules
- Terraform Public Modules
- Terraform local modules
- Terraform Module Versioning
- Terraform Nested Modules
Provisioners & Lifecycle
🧠 Terraform Provisioners: Run Scripts (local-exec, remote-exec) During Deployment
Terraform is an Infrastructure as Code (IaC) tool that automates the creation and management of cloud resources. While Terraform primarily focuses on declaring infrastructure, sometimes you need to run commands or scripts on your local machine or remote servers during or after resource creation.
This is where Terraform Provisioners come in.
💡 Simple Definition
Provisioners in Terraform allow you to execute scripts or commands on your local system or remote servers during the resource creation or destruction process.
They bridge the gap between infrastructure provisioning and software configuration.
🔹 Common Use Cases
- Bootstrapping an instance (e.g., installing software packages)
- Configuring applications after deployment
- Executing initialization scripts
- Copying configuration files to remote machines
- Cleaning up resources during destruction
🔹 Types of Terraform Provisioners
Terraform provides several types of provisioners:
Provisioner | Description |
---|---|
local-exec | Runs a command locally on the machine where Terraform is executed |
remote-exec | Runs commands remotely on a resource (like a VM) via SSH or WinRM |
file | Uploads a file or directory to a remote resource |
null_resource | Acts as a placeholder for running provisioners without creating actual resources |
🔹 — Provisioner Flow
Explanation: When Terraform creates a resource, the associated provisioners are triggered. They execute scripts locally or remotely and then return the execution status back to Terraform.
🔹 Syntax of a Provisioner
Here’s the general syntax used inside a resource block:
resource "aws_instance" "example" { ami = "ami-123456" instance_type = "t2.micro"
provisioner "local-exec" { command = "echo 'Instance Created Successfully!'" }}
🔹 Example 1: Using local-exec Provisioner
The local-exec provisioner runs a command on the local machine where Terraform is executed. It’s ideal for tasks like logging, API calls, or triggering CI/CD steps.
✅ Example Code
provider "aws" { region = "us-east-1"}
resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro"
provisioner "local-exec" { command = "echo 'Deployed ${self.id} to AWS' >> deploy_log.txt" }}
Explanation:
- The
local-exec
runs on your local terminal. ${self.id}
dynamically refers to the instance’s ID.- The result is saved in a log file
deploy_log.txt
.
🧩 Output Example
$ terraform applyaws_instance.web: Creating...aws_instance.web: Provisioning with 'local-exec'...Deployed i-09f1a34f28f to AWS
🔹 Example 2: Using remote-exec Provisioner
The remote-exec provisioner allows you to execute commands on the remote server after it’s created. This is commonly used for bootstrapping software installations or running setup scripts.
✅ Example Code
provider "aws" { region = "us-east-1"}
resource "aws_instance" "app_server" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" key_name = "my-key"
provisioner "remote-exec" { inline = [ "sudo apt-get update -y", "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:
- Terraform connects to the instance using SSH.
- It installs and starts Nginx.
- You can use this to perform post-deployment configuration.
🧩 Output Example
$ terraform applyaws_instance.app_server: Provisioning with 'remote-exec'...Installing Nginx...Nginx started successfully!
🔹 Example 3: Using file Provisioner
The file provisioner is used to copy files or directories from your local system to a remote instance.
✅ Example Code
provider "aws" { region = "us-east-1"}
resource "aws_instance" "config_server" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" key_name = "my-key"
provisioner "file" { source = "app_config.txt" destination = "/home/ubuntu/app_config.txt"
connection { type = "ssh" user = "ubuntu" private_key = file("~/.ssh/my-key.pem") host = self.public_ip } }
provisioner "remote-exec" { inline = [ "cat /home/ubuntu/app_config.txt", "echo 'Configuration Deployed!'" ]
connection { type = "ssh" user = "ubuntu" private_key = file("~/.ssh/my-key.pem") host = self.public_ip } }}
Explanation:
- The file provisioner uploads
app_config.txt
to the remote server. - The remote-exec then verifies and prints the contents.
🔹 Example 4: Combining Provisioners with Null Resource
When you want to run scripts without creating actual resources, use null_resource
.
resource "null_resource" "run_script" { provisioner "local-exec" { command = "bash ./scripts/setup_env.sh" }}
Use Case: This approach is great for CI/CD jobs, database migrations, or local validations.
🔹 Lifecycle Behavior
Provisioners are executed during the creation or destruction of a resource.
Execution Order:
- Terraform creates the resource.
- Runs the provisioner (local or remote).
- Marks the resource as “created.”
You can control when provisioners run using when
:
provisioner "local-exec" { when = "destroy" command = "echo 'Cleaning up resource...'"}
This runs the command before destroying the resource.
🔹 — Execution Order
🔹 How to Remember Provisioners (Mnemonic)
Use the acronym “L.R.F” — Local, Remote, File 🧠
Letter | Meaning | Function |
---|---|---|
L | Local-exec | Runs commands locally |
R | Remote-exec | Runs commands remotely |
F | File | Uploads files to remote hosts |
💡 Memory Trick:
“Provisioners help Terraform Link, Run, and File your configurations during deployments.”
🔹 Terraform Provisioners in Interview and Exams
🎯 Frequently Asked Questions
Q1. What are Terraform provisioners used for? 👉 To execute local or remote scripts during resource creation or destruction.
Q2. Difference between local-exec and remote-exec?
👉 local-exec
runs on the Terraform host; remote-exec
runs inside the provisioned resource.
Q3. What is a null_resource? 👉 A dummy resource used to run provisioners without creating actual cloud resources.
Q4. Are provisioners recommended in production? 👉 Only when necessary — Terraform recommends configuration management tools (like Ansible) for heavy software setup.
Q5. How to handle errors in provisioners?
👉 Use on_failure = continue
to prevent Terraform from halting execution.
🧠 Exam & Study Tip
Use this phrase to memorize:
“Provisioners run code while Terraform builds nodes.”
To remember:
- Local-exec → Local machine tasks
- Remote-exec → SSH/WinRM commands
- File → Copy configuration files
And always remember: Provisioners are last-resort tools — not the main automation mechanism.
🔹 Why It’s Important to Learn Terraform Provisioners
Reason | Explanation |
---|---|
Bridges IaC and Automation | Lets Terraform trigger scripts and commands automatically |
Post-deployment configuration | Install or configure software right after instance creation |
Flexibility | Runs both local and remote tasks seamlessly |
Real-world use | Used in multi-step infrastructure setups |
Exam relevance | Terraform Associate Exam includes questions on provisioner usage |
CI/CD Integration | Helps integrate Terraform into pipelines by executing hooks |
🔹 Best Practices
Best Practice | Description |
---|---|
Use provisioners sparingly | Prefer configuration tools (Ansible, Chef, Puppet) |
Handle errors gracefully | Use on_failure = continue |
Avoid sensitive data exposure | Don’t echo secrets into logs |
Use depends_on to control order | Ensure correct resource dependencies |
Combine with null_resource | For script-only automation |
Document scripts | Maintain clear README for team understanding |
🔹 Common Mistakes to Avoid
Mistake | Why It’s Problematic | Solution |
---|---|---|
Overusing provisioners | Makes Terraform impure and state-heavy | Limit usage to bootstrapping |
Ignoring SSH issues | Fails remote-exec | Validate SSH keys before use |
No error handling | Terraform halts unexpectedly | Add on_failure parameter |
Hardcoded paths | Reduces portability | Use variables or path.module |
Unnecessary dependencies | Slows down builds | Simplify workflow |
🔹 Real-World Use Cases
-
Cloud Bootstrapping:
- Automatically install web servers or dependencies.
-
File Uploading:
- Send configuration templates or credentials securely.
-
CI/CD Integration:
- Trigger Jenkins or GitHub Actions pipelines after deployments.
-
Security Audits:
- Execute compliance validation scripts post-deployment.
-
Hybrid Infrastructure:
- Configure both on-prem and cloud nodes via provisioners.
🔹 Summary Table
Provisioner | Runs On | Usage Example | Typical Use Case |
---|---|---|---|
local-exec | Local Machine | echo "Done" | CI/CD hooks, logs |
remote-exec | Remote Server | apt install nginx | Bootstrapping servers |
file | Remote Server | Upload config files | Deploying configurations |
null_resource | None | Run local scripts | Script automation |
🔹 Quick Demo Workflow
terraform initterraform validateterraform planterraform apply
Observe the log output — you’ll see provisioners executing commands during deployment.
🔹 Summary Diagram
Terraform Provisioners act as the “final step” between infrastructure creation and environment readiness. They allow you to:
- Execute local commands (
local-exec
) - Run remote setup scripts (
remote-exec
) - Transfer files (
file
) - Trigger custom automation (
null_resource
)
However, Terraform is not a configuration management tool — use provisioners only for minimal bootstrapping or integration hooks.
💬 “Provisioners are Terraform’s glue — connecting your infrastructure with automation logic.”
By mastering provisioners, you gain the flexibility to automate any deployment task, ensuring your cloud infrastructure is both ready and reliable.