π― 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)