๐ฏ Goal
Provision an EC2 instance that:
- Installs Nginx automatically
- Starts the service
- Serves a custom web page
๐ All using user_data (bootstrapping)
๐ Project Structure
terraform-userdata-lab/
โโโ main.tf
โโโ variables.tf
โโโ terraform.tfvars
โโโ providers.tf
โโโ versions.tf
โโโ outputs.tf
โโโ user_data.sh.tpl
๐ versions.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
๐ providers.tf
provider "aws" {
region = var.aws_region
}
๐ variables.tf
variable "aws_region" {
type = string
description = "AWS region"
}
variable "instance_type" {
type = string
description = "EC2 type"
}
variable "instance_name" {
type = string
description = "Name of instance"
}
variable "web_message" {
type = string
description = "Message shown on web page"
}
variable "common_tags" {
type = map(string)
description = "Common tags"
}
๐ terraform.tfvars
aws_region = "us-east-2"
instance_type = "t2.micro"
instance_name = "userdata-lab"
web_message = "Hello from Terraform User Data!"
common_tags = {
Project = "UserDataLab"
Owner = "Student"
}
๐ user_data.sh.tpl (IMPORTANT)
#!/bin/bash
yum update -y
yum install -y nginx
systemctl start nginx
systemctl enable nginx
echo "${web_message}" > /usr/share/nginx/html/index.html
๐ main.tf
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_security_group" "web_sg" {
name = "${var.instance_name}-sg"
description = "Allow HTTP"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = var.common_tags
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.web_sg.id]
user_data = templatefile("${path.module}/user_data.sh.tpl", {
web_message = var.web_message
})
tags = merge(var.common_tags, {
Name = var.instance_name
})
}
๐ outputs.tf
output "public_ip" {
value = aws_instance.web.public_ip
}
output "url" {
value = "http://${aws_instance.web.public_ip}"
}
๐งช STEP-BY-STEP
โ Step 1 โ Initialize
terraform init
โ Step 2 โ Apply
terraform apply
โ Step 3 โ Open browser
Use output:
terraform output url
๐ Open in browser
๐ You will see:
Hello from Terraform User Data!
๐ฅ What is user_data (Important Explanation)
๐ user_data is a script that runs:
- Automatically when EC2 starts
- Only on first boot (by default)
๐ง Real DevOps Usage
Used for:
- Install packages (nginx, docker)
- Configure apps
- Pull code from Git
- Start services
โ ๏ธ Important Notes
โ Runs only once
If you change user_data:
๐ Terraform does NOT re-run it
โ To re-run:
You must:
terraform taint aws_instance.web
terraform apply
OR change:
user_data_replace_on_change = true
๐ฅ Bonus (VERY IMPORTANT FOR INTERVIEW)
Add this:
user_data_replace_on_change = true
๐ Now:
- Any change in user_data โ instance recreated
๐ฏ Interview Answer
Q: What is user_data in Terraform?
๐
user_data is a script passed to an EC2 instance that runs during the initial boot process, typically used to install software and configure the instance automatically.
๐ Summary
| Feature | Purpose |
|---|---|
| user_data | Bootstrap EC2 |
| templatefile | Avoid hardcoding |
| runs | On first boot |
| replace_on_change | Forces recreation |
Top comments (0)