Have you ever passed the data or any script on any compute resource while creating? Most of you might have passed the user data or scripts after creating the resource. Consider using Terraform provisioners if you want to pass the data even before the resource is created.
Terraform provisioners allow to pass data in any resource that cannot be passed when creating resources. Multiple terraform provisioners can be specified within a resource block and executed in the order they’re defined in the configuration file.
In this tutorial, you will learn how to work with multiple Terraform Provisioners using Terraform. Let’s get into it.
Table of Content
- What is Terraform provisioners?
- Prerequisites
- Terraform files and Terraform directory structure
- Building Terraform configuration files to use Terraform provisioners on AWS EC2 instance.
- Verifying the Softwares in AWS EC2 instance created using Terraform Provisioner
- Conclusion
What is Terraform provisioners?
Do you know what Terraform allows you to perform an action on your local machine or remote machine such as running a command on the local machine, copying files from local to remote machines or vice versa, Passing data into virtual machines, etc. all this can be done by using Terraform provisioner?
Terraform provisioners allow to pass data in any resource that cannot be passed when creating resources. Multiple terraform provisioners can be specified within a resource block and executed in the order they’re defined in the configuration file.
The terraform provisioners interact with remote servers over SSH or WinRM. Most cloud computing platforms provide mechanisms to pass data to instances at the time of their creation such that the data is immediately available on system boot. Still, you can pass the data with Terraform provisioners even after creating the resource.
Terraform provisioners allows you to declare conditions such as when = destroy
, on_failure = continue
and If you wish to run terraform provisioners that aren’t directly associated with a specific resource, use null_resource
.
Prerequisites
- Ubuntu machine to run terraform command, if you don’t have Ubuntu machine you can create an AWS EC2 instance on AWS account with 4GB RAM and at least 5GB of drive space.
- Terraform Installed on Ubuntu Machine. If you don’t have Terraform installed refer Terraform on Windows Machine / Terraform on Ubuntu Machine
- Ubuntu machine should have IAM role attached with complete AWS EC2 permissions or administrator rights.
You may incur a small charge for creating an EC2 instance on Amazon Managed Web Service.
Terraform files and Terraform directory structure
Now that you know what is Amazon Elastic search and Amazon OpenSearch service are. Let’s now dive into Terraform files and Terraform directory structure that will help you write the Terraform configuration files later in this tutorial.
Terraform code, that is, Terraform configuration files, are written in a tree-like structure to ease the overall understanding of code with .tf format
or .tf.json
or .tfvars
format. These configuration files are placed inside the Terraform modules.
Terraform modules are on the top level in the hierarchy where configuration files reside. Terraform modules can further call another child to terraform modules from local directories or anywhere in disk or Terraform Registry.
Terraform contains mainly five files as main.tf , vars.tf , providers.tf , output.tf and terraform.tfvars.
- main.tf – Terraform main.tf file contains the main code where you define which resources you need to build, update or manage.
- vars.tf – Terraform vars.tf file contains the input variables which are customizable and defined inside the main.tf configuration file.
- output.tf : The Terraform output.tf file is the file where you declare what output paraeters you wish to fetch after Terraform has been executed that is after terraform apply command.
- .terraform: This directory contains
cached provider
, modules plugins and also contains the last known backend configuration. This is managed by terraform and created after you runterraform init
command. - terraform.tfvars files contains the values which are required to be passed for variables that are refered in main.tf and actually decalred in vars.tf file.
- providers.tf – The povider.tf is the most important file whrere you define your terraform providers such as terraform aws provider, terraform azure provider etc to authenticate with the cloud provider.
Building Terraform configuration files to use Terraform provisioners on AWS EC2 instance.
Now that you know what are Terraform configurations files and how to declare each of them. In this section, you will learn how to build Terraform configuration files by using multiple provisioners to work with the AWS EC2 instance. Let’s get into it.
- Log in to the Ubuntu machine using your favorite SSH client.
- Create a folder in opt directory named terraform-provisioners-demo and switch to that folder.
mkdir /opt/terraform-provisioners-demo
cd /opt/terraform-provisioners-demo
- Create a file named main.tf inside the /opt/terraform-provisioners-demo directory and copy/paste the below content. The main.tf file performs the following thing:
- Creates a secret key pair (public and private keys) so that provisioners use it to connect and login to machine over SSH protocol .
- Next, using the local exec provisioners Terraform executes command locally on your machine.
- The remote exec provisioners installs software (Apache) on AWS EC2 instance.
- Finally, the file Provisioner uploads the file (file.json) in the AWS EC2 instance.
# Creating the Key pair on AWS
resource "aws_key_pair" "deployer" {
key_name = "deployer-key"
# public_key generates the private and public key on local machine
public_key = "${file("~/.ssh/id_rsa.pub")}"
}
# Creating the instance
resource "aws_instance" "my-machine" {
ami = "ami-0a91cd140a1fc148a"
key_name = aws_key_pair.deployer.key_name
instance_type = "t2.micro"
# Declaring the first provisioner
provisioner "local-exec" {
command = "echo ${aws_instance.my-machine.private_ip} >> ip.txt"
on_failure = continue
}
# Declaring the second provisioner which needs SSH/Winrm connection
provisioner "remote-exec" {
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file("~/.ssh/id_rsa")}"
agent = false
host = aws_instance.my-machine.public_ip
timeout = "30s"
}
inline = [
"sudo apt install -y apache2",
]
}
# Declaring the third provisioner that also needs SSH/Winrm connection
provisioner "file" {
source = "C:\\Users\\4014566\\Desktop\\service-policy.json"
destination = "/tmp/file.json"
connection {
type = "ssh"
user = "ubuntu"
host = aws_instance.my-machine.public_ip
private_key = "${file("~/.ssh/id_rsa")}"
agent = false
timeout = "30s"
}
}
- Create one more file provider.tf file inside the /opt/terraform-s3-demo directory and copy/paste below content. The provider.tf file will allows Terraform to connect to the AWS cloud.
provider "aws" {
region = "us-east-2"
}
- Now your files and code are ready for execution. Initialize the terraform using the terraform init command.
terraform init

- Terraform initialized successfully , now its time to run the plan command which provides you the details of the deployment. Run terraform plan command to confirm if correct resources is going to provisioned or deleted.
terraform plan
- After verification, now its time to actually deploy the code using terraform apply command.
terraform apply

Verifying the Softwares in AWS EC2 instance created using Terraform Provisioner
Terraform commands terraform init
→ terraform plan
→ terraform apply
all executed successfully. But it is important to manually verify the software on the AWS EC2.
As you can see below, the file.json is copied successfully, and also apache installation is successful.

Conclusion
This tutorial taught you what Terraform provisioners are and how to work with various Terraform provisioners using Terraform on AWS.
Now that you have a newly created AWS instance, what do you plan to copy on it using Terraform provisioner?