What is user_data in Terraform?
Table of Content
- What is user_data in Terraform?
- When to use user_data in Terraform?
- Terraform user_data : How to execute shell script inside EC2 instance using?
- How to accomplish common tasks - Folder creation, Package installation with Terraform user_data
- How to use ${file("")} function with user_data?
- Using template_file with user_data
- Conclusion
What is user_data in Terraform?
In Terraform, the user_data attribute is used to pass data to an instance at launch time. It is specified as a string in the Terraform configuration file and can contain any valid data that is base64-encoded when the instance launches.
Here is an example of user_data
attribute when I am setting up an EC2
instance -
1#maint.tf
2
3resource "aws_instance" "example" {
4 ami = "ami-0767046d1677be5a0"
5 instance_type = "t2.micro"
6
7 # user_data attribute - Create a txt file inside EC2 instance
8 user_data = <<-EOF
9 #!/bin/bash
10 echo "Hello, World!" > hello.txt
11 EOF
12}
Here is how the above example works -
- The above example will create an EC2 instance using the specified AMI and instance type, and passes a script to the instance as user data.
- The script will run when the instance launches, creating a file called
hello.txt
that contains the stringHello, World!
. - The
user_data
attribute is only used at the time the instance is launched
When to use user_data in Terraform?
Here are five common use cases for the user_data attribute in Terraform:
- Installing software or packages: Installing software or packages on an instance at launch time. For example, you might use user_data to install a web server or database server when an instance is launched.
- Configuring the instance: Configuring the instance to run a specific application or service. For example, you might use user_data to configure an instance to run a web application.
- Setting the hostname or other instance metadata: Setting the hostname or other instance metadata. This can be useful for identifying instances in a cluster or for customizing the instance's environment.
- Configuring the instance: Configuring the instance to communicate with other resources, such as an S3 bucket or a database.
- Automating the setup: Automating the setup of an instance when it is launched, rather than manually configuring it after it has been launched. This can save time and effort when launching multiple instances.
Terraform user_data : How to execute shell script inside EC2 instance using?
Let's take a very basic example of user_data
attribute in which we are going to execute the script inside an EC2 instance on AWS.
Here is an example code and here is the sequence of execution -
- First we will write
user_data
attribute block inside the terraformmain.tf
- Inside the
user_data
block we are going to write a shell command to generate the text file -echo "Hello World" > hello.txt
- At last we are going to execute the code using
terraform init, terraform plan and terraform apply command
- End Result: The shell script will create a hello.txt file at root directory of EC2 Instance.
1#maint.tf
2
3resource "aws_instance" "example" {
4 ami = "ami-0767046d1677be5a0"
5 instance_type = "t2.micro"
6
7 # user_data attribute - Create a txt file inside the EC2 instance
8 user_data = <<-EOF
9 #!/bin/bash
10 echo "Hello, World!" > hello.txt
11 EOF
12}
Here is a screenshot from the root directory of the EC2 Instance and you can see we have created a file hello.txt
-
How to accomplish common tasks - Folder creation, Package installation with Terraform user_data
In the previous point we have seen a very basic example of how to execute a very simple shell script using the user_data
block of terraform.
Let's take one step further and this time we will try to accommodate some more common stuff for example - folder creation, Linux package installation
Task: Install python and Nginx server using user_data
Here is how we are gonna perform common tasks with user_data
-
- Create a directory using the command -
mkdir /opt/myapp
- Install python with the command -
sudo apt install python3
- Install nginx using the command -
sudo apt install nginx
Let's create one bash script for all the above common tasks-
Here is the bash script version of all the common tasks which I have mentioned above
1#!/bin/bash
2
3# Create a new directory
4mkdir /opt/myapp
5
6# Install python
7sudo apt install python3
8
9# Install nginx
10sudo apt install nginx
Create main.tf with user_data : In this main.tf
first we are going to create aws_instance
then in the user_data
section common tasks script will be executed.
1# main.tf
2
3resource "aws_instance" "example" {
4 ami = "ami-0767046d1677be5a0"
5 instance_type = "t2.micro"
6
7 # user_data attribute performing common tasks
8 # 1. Create a new directory
9 # 2. Install python
10 # 3. Install nginx
11 user_data = <<-EOF
12 #!/bin/bash
13
14 # Create a new directory
15 mkdir /opt/myapp
16
17 # Install python
18 sudo apt install python3
19
20 # Install nginx
21 sudo apt install nginx
22 EOF
23}
How to use ${file("")} function with user_data?
In this section, we are going to use the file
function in Terraform to read the contents of a file and pass it to the user_data
attribute of an instance resource. Here is an example of how to use the file
function with user_data
:
1#main.tf
2
3provider "aws" {
4 region = "eu-central-1"
5 shared_credentials_files = ["/Users/rahulwagh/.aws/credentials"]
6}
7
8
9resource "aws_instance" "example" {
10 ami = "ami-0767046d1677be5a0"
11 instance_type = "t2.micro"
12 vpc_security_group_ids = [aws_security_group.main.id]
13 key_name= "aws_key"
14 user_data = "${file("install_apache.sh")}"
15}
In the above example, the file function reads the contents of the install_nginx.sh
file and passes it to the user_data attribute of the aws_instance
resource.
Here is the content of install_nginx.sh
:
1#! /bin/bash
2sudo apt-get update
3sudo apt-get install -y apache2
4sudo systemctl start apache2
5sudo systemctl enable apache2
6echo "<h1>Welcome : Apache installed with the help of user_data and file function</h1>" | sudo tee /var/www/html/index.html
Where to place the file? : You should be careful about the placement of the file
which will be read by the user_data
. Here is the screenshot of my project where I have placed the install_nginx.sh
at the same location where my main.tf
is present.
In case your file is present at some other location then you should use the relative path to load the file using the ${file("")}
function.
Using template_file with user_data
In the next combination, we are going to use template_file
resource along with user_data
.
But before that let's recap a bit - In the previous section we have hard coded the script inside the user_data
block which is perfectly fine and also loaded the large file
using the ${file("")}
.
But sometimes both options are not sufficient to implement certain tasks with user_data
block. You need to have dynamic template where you can update the script at run time and to achieve that we can also use the template_file
resource along with user_block
in terraform.
Here is an example code on how to do that -
- Create Bash file- First create bash script file
install_nginx.sh
1#! /bin/bash
2sudo apt-get update
3sudo apt-get install -y apache2
4sudo systemctl start apache2
5sudo systemctl enable apache2
6echo "<h1>Welcome : Apache installed with the help of user_data and file function</h1>" | sudo tee /var/www/html/index.html
- Create main.tf and call template_file - Now let's create
main.tf
and also createtemplate_file
block to render the template file .i.e.install_nginx.sh
. You can create terraform template with any extension for example - .json, .sh, .tpl
1#main.tf
2
3# Refer to the template file - install_nginx.sh
4resource "template_file" "user_data" {
5 template = "${file("install_nginx.sh")}"
6
7 vars {
8 package = "nginx"
9 command = "systemctl start nginx"
10 }
11}
12
13resource "aws_instance" "example" {
14 ami = "ami-12345678"
15 instance_type = "t2.micro"
16
17 # user_data : render the template
18 user_data = "${template_file.user_data.rendered}"
19}
- Finally you can run the
terraform init, terraform plan and terraform apply
commands.
Conclusion
If you are reading the conclusion part of this blog post then I would you have pretty much covered all the basic knowledge which is necessary for using the user_data
. In an actual production environment, you might see more complex use cases where you will be a lot more complex stuff rather than just creating the folder and installing the package. But this blog post serves you a good start with user_data
. For more practical stuff you can follow me on youtube as well.
Posts in this Series
- Use Terraform to manage AWS IAM Policies, Roles and Users
- How to split Your Terraform main.tf File into Multiple Files
- How to use Terraform variable within variable
- Mastering the Terraform Lookup Function for Dynamic Keys
- Copy files to EC2 and S3 bucket using Terraform
- Troubleshooting Error creating EC2 Subnet InvalidSubnet Range The CIDR is Invalid
- Troubleshooting InvalidParameter Security group and subnet belong to different networks
- Managing strings in Terraform: A comprehensive guide
- How to use terraform depends_on meta argument?
- What is user_data in Terraform?
- Why you should not store terraform state file(.tfstate) inside Git Repository?
- How to import existing resource using terraform import comand?
- Terraform - A detailed guide on setting up ALB(Application Load Balancer) and SSL?
- Testing Infrastructure as Code with Terraform?
- How to remove a resource from Terraform state?
- What is Terraform null Resource?
- In terraform how to skip creation of resource if the resource already exist?
- How to setup Virtual machine on Google Cloud Platform
- How to use Terraform locals?
- Terraform Guide - Docker Containers & AWS ECR(elastic container registry)?
- How to generate SSH key in Terraform using tls_private_key?
- How to fix-Terraform Error acquiring the state lock ConditionalCheckFiledException?
- Terraform Template - A complete guide?
- How to use Terragrunt?
- Terraform and AWS Multi account Setup?
- Terraform and AWS credentials handling?
- How to fix-error configuring S3 Backend no valid credential sources for S3 Backend found?
- Terraform state locking using DynamoDB (aws_dynamodb_table)?
- Managing Terraform states?
- Securing AWS secrets using HashiCorp Vault with Terraform?
- How to use Workspaces in Terraform?
- How to run specific terraform resource, module, target?
- How Terraform modules works?
- Secure AWS EC2s & GCP VMs with Terraform SSH Keys!
- What is terraform provisioner?
- Is terraform destroy needed before terraform apply?
- How to fix terraform error Your query returned no results. Please change your search criteria and try again?
- How to use Terraform Data sources?
- How to use Terraform resource meta arguments?
- How to use Terraform Dynamic blocks?
- Terraform - How to nuke AWS resources and save additional AWS infrastructure cost?
- Understanding terraform count, for_each and for loop?
- How to use Terraform output values?
- How to fix error configuring Terraform AWS Provider error validating provider credentials error calling sts GetCallerIdentity SignatureDoesNotMatch?
- How to fix Invalid function argument on line in provider credentials file google Invalid value for path parameter no file exists
- How to fix error value for undeclared variable a variable named was assigned on the command line?
- What is variable.tf and terraform.tfvars?
- How to use Terraform Variables - Locals,Input,Output
- Terraform create EC2 Instance on AWS
- How to fix Error creating service account googleapi Error 403 Identity and Access Management (IAM) API has not been used in project before or it is disabled
- Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11