Terraform Provisioners
Imagine you’ve just built a brand‑new house with Terraform. The structure is solid, but it’s empty without furniture, no wiring, no paint. You need a way to run commands inside the house to finish setup.
That’s what provisioners do in Terraform: they let you run scripts or commands on resources after they’re created, bridging the gap between infrastructure provisioning and configuration management.
Provisioners are not meant to replace tools like Ansible, Chef, or Puppet, but they act as a last‑mile helper when you need quick setup tasks directly from Terraform.
Key Concepts
1. What is a Provisioner?
- A provisioner is a Terraform mechanism to run scripts or commands on a resource after it’s created or destroyed.
- Types include:
local-exec→ Runs a command locally on the machine running Terraform.remote-exec→ Runs commands on a remote resource via SSH or WinRM.file→ Copies files from local to remote resources.
2. Why Use Provisioners?
- Bootstrapping: Install software or configure a resource immediately after creation.
- Quick fixes: Run ad‑hoc scripts without a full configuration management tool.
- Integration: Trigger external processes (e.g., notify CI/CD pipeline).
- Cleanup: Run commands when destroying resources (e.g. deregister from monitoring).
3. Example Use Cases
- Install Apache on a new EC2 instance using
remote-exec. - Copy configuration files to a VM using
file. - Trigger a shell script locally after infra deployment using
local-exec. - Run cleanup scripts when destroying resources.
4. Limitations & Cautions
- Provisioners are not idempotent which means they don’t guarantee repeatable results.
- Failures can cause Terraform runs to fail unpredictably.
- Better suited for small tasks, not full configuration management.
- Use sparingly - prefer dedicated tools (Ansible, Chef, Puppet) for complex setups.
Hands‑On Lab / Demo
Lab: Using a local-exec Provisioner
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo Instance ${self.id} created >> instances.log"
}
}
- After the instance is created, Terraform logs its ID locally.
Lab: Using a remote-exec Provisioner
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y apache2"
]
}
}
- Installs Apache on the EC2 instance immediately after creation.
Pro Tips & Best Practices
- Use provisioners only for tasks that cannot be handled otherwise.
- Keep scripts simple and idempotent.
- Always test provisioners in staging before production.
- Prefer configuration management tools for complex setups.
- Document why a provisioner is used - future maintainers will thank you.
Summary & Cheatsheet
- Provisioners = Last‑mile helpers.
- Types:
local-exec,remote-exec,file. - Use cases: bootstrapping, quick fixes, integration, cleanup.
- Limitations: not idempotent, fragile, use sparingly.
Quick mnemonic: Provisioners = Run, Fix, Finish
The Hackers Notebook
Provisioners are the bridge between infrastructure and configuration. They let you run commands or scripts directly from Terraform, making them handy for bootstrapping and quick fixes. But like duct tape, they’re best used sparingly.
