Tools: Breaking: LAB: Terraform EC2 with `user_data`
๐ฏ Goal
๐ Project Structure
๐ versions.tf
๐ providers.tf
๐ variables.tf
๐ terraform.tfvars
๐ user_data.sh.tpl (IMPORTANT)
๐ main.tf
๐ outputs.tf
๐งช STEP-BY-STEP
โ Step 1 โ Initialize
โ Step 2 โ Apply
โ Step 3 โ Open browser
๐ฅ What is user_data (Important Explanation)
๐ง Real DevOps Usage
โ ๏ธ Important Notes
โ Runs only once
โ To re-run:
๐ฅ Bonus (VERY IMPORTANT FOR INTERVIEW)
๐ฏ Interview Answer
๐ Summary Provision an EC2 instance that: ๐ All using user_data (bootstrapping) ๐ Open in browser
๐ You will see: ๐ user_data is a script that runs: If you change user_data: ๐ Terraform does NOT re-run it 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. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse
terraform-userdata-lab/
โโโ main.tf
โโโ variables.tf
โโโ terraform.tfvars
โโโ providers.tf
โโโ versions.tf
โโโ outputs.tf
โโโ user_data.sh.tpl
terraform-userdata-lab/
โโโ main.tf
โโโ variables.tf
โโโ terraform.tfvars
โโโ providers.tf
โโโ versions.tf
โโโ outputs.tf
โโโ user_data.sh.tpl
terraform-userdata-lab/
โโโ main.tf
โโโ variables.tf
โโโ terraform.tfvars
โโโ providers.tf
โโโ versions.tf
โโโ outputs.tf
โโโ user_data.sh.tpl
terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }
}
terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }
}
terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }
}
provider "aws" { region = var.aws_region
}
provider "aws" { region = var.aws_region
}
provider "aws" { region = var.aws_region
}
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"
}
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"
}
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"
}
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"
}
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"
}
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"
}
#!/bin/bash
yum update -y
yum install -y nginx systemctl start nginx
systemctl enable nginx echo "${web_message}" > /usr/share/nginx/html/index.html
#!/bin/bash
yum update -y
yum install -y nginx systemctl start nginx
systemctl enable nginx echo "${web_message}" > /usr/share/nginx/html/index.html
#!/bin/bash
yum update -y
yum install -y nginx systemctl start nginx
systemctl enable nginx echo "${web_message}" > /usr/share/nginx/html/index.html
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 })
}
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 })
}
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 })
}
output "public_ip" { value = aws_instance.web.public_ip
} output "url" { value = "http://${aws_instance.web.public_ip}"
}
output "public_ip" { value = aws_instance.web.public_ip
} output "url" { value = "http://${aws_instance.web.public_ip}"
}
output "public_ip" { value = aws_instance.web.public_ip
} output "url" { value = "http://${aws_instance.web.public_ip}"
}
terraform init
terraform init
terraform init
terraform apply
terraform apply
terraform apply
terraform output url
terraform output url
terraform output url
Hello from Terraform User Data!
Hello from Terraform User Data!
Hello from Terraform User Data!
terraform taint aws_instance.web
terraform apply
terraform taint aws_instance.web
terraform apply
terraform taint aws_instance.web
terraform apply
user_data_replace_on_change = true
user_data_replace_on_change = true
user_data_replace_on_change = true
user_data_replace_on_change = true
user_data_replace_on_change = true
user_data_replace_on_change = true - Installs Nginx automatically
- Starts the service
- Serves a custom web page - Automatically when EC2 starts
- Only on first boot (by default) - Install packages (nginx, docker)
- Configure apps
- Pull code from Git
- Start services - Any change in user_data โ instance recreated