
Terraform is widely known for its ability to provision infrastructure as code, but did you know it can also help you perform post-provisioning tasks on your instances? That’s where provisioners come in.
In this article, we’ll break down what Terraform provisioners are, why they’re useful, and how they work — using a real-world example where we deploy a Flask web application on an AWS EC2 instance with Terraform.
What Are Terraform Provisioners?
Provisioners in Terraform allow you to execute scripts or commands on a local or remote machine once the infrastructure has been provisioned. This is especially useful when:
- Installing software on a virtual machine.
- Uploading configuration files or app code.
- Bootstrapping resources before or after deployment.
🔥 Note: While powerful, provisioners are considered a last resort in many cases. It’s generally better to use configuration management tools like Ansible or cloud-init for post-deployment configuration. But for simple tasks or demos, provisioners are perfectly fine.
Types of Provisioners
Terraform supports several types of provisioners. The most commonly used are:
- file — Uploads files or directories to a remote machine.
- remote-exec — Executes commands on a remote resource over SSH or WinRM.
- local-exec — Runs commands on your local machine after applying the resource.
In this article, we’ll focus on file and remote-exec.
Project Overview
We’ll use a project that provisions an AWS VPC, subnet, security group, and EC2 instance, then deploys a Flask web app to the EC2 instance using provisioners.
GitHub Repository
You can find all the code examples used in this guide in my GitHub repository:
Using Provisioners in Terraform
Here’s how we used provisioners in the main.tf file of our project:
Connection Block
Before using provisioners, we define how Terraform will connect to the EC2 instance:
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}This tells Terraform to SSH into the instance using the provided private key and public IP.
file Provisioner
The file provisioner is used to upload our Flask app to the EC2 instance:
provisioner "file" {
source = "app.py"
destination = "/home/ubuntu/app.py"
}Explanation:
- source: Path to the file on your local machine.
- destination: Path on the remote EC2 instance.
remote-exec Provisioner
This provisioner runs a series of commands on the EC2 instance to install Python and Flask, and launch the app:
provisioner "remote-exec" {
inline = [
"echo 'Hello from the Remote Instance'",
"sudo apt update -y",
"sudo apt-get install -y python3-pip",
"cd /home/ubuntu",
"sudo pip3 install flask",
"sudo python3 app.py &"
]
}Explanation:
- We update the package list.
- Install pip, the Python package manager.
- Install Flask.
- Run the app on port 80 in the background (&).
🛑 Ensure port 80 is open in your security group to access the Flask app from your browser.
Why Not Just Use AMIs or Cloud-Init?
Great question! While custom AMIs or cloud-init scripts are preferred in production, provisioners are handy for:
- Prototyping and demos.
- Learning infrastructure automation.
- One-time setup tasks that don’t justify a new AMI.
Best Practices and Gotchas
- Use provisioners only when absolutely necessary.
- Always provide a valid SSH key and security group rules for connectivity.
- Consider the lifecycle and dependencies carefully — if a provisioner fails, Terraform may mark the resource as tainted.
- Use depends_on to explicitly manage execution order if needed.
Clean Up
Once you’re done testing:
terraform destroy
This removes all infrastructure and avoids unnecessary AWS charges.
Conclusion
Terraform provisioners are powerful tools for automating what happens after your infrastructure is deployed. Whether it’s copying files or running commands remotely, they give you the ability to go beyond just setting up infrastructure.
Using this simple Flask app deployment on AWS EC2, you’ve now seen provisioners in action!
🚀 Let’s Connect!
If you found this guide helpful, follow me for more DevOps and Cloud Engineering content:
🔗 GitHub → github.com/Dhanika-Kumarasiri
🔗 Medium → medium.com/@dhanika-kumarasiri
Have questions? Drop them in the comments! Let’s automate AWS the smart way! 🚀