Tools: Breaking: LAB: Terraform EC2 with `user_data`

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

Code Block

Copy

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