DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

LAB: Terraform EC2 with `user_data`

🎯 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
Enter fullscreen mode Exit fullscreen mode

πŸ“„ versions.tf

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“„ providers.tf

provider "aws" {
  region = var.aws_region
}
Enter fullscreen mode Exit fullscreen mode

πŸ“„ 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"
}
Enter fullscreen mode Exit fullscreen mode

πŸ“„ 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"
}
Enter fullscreen mode Exit fullscreen mode

πŸ“„ 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
Enter fullscreen mode Exit fullscreen mode

πŸ“„ 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
  })
}
Enter fullscreen mode Exit fullscreen mode

πŸ“„ outputs.tf

output "public_ip" {
  value = aws_instance.web.public_ip
}

output "url" {
  value = "http://${aws_instance.web.public_ip}"
}
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ STEP-BY-STEP


βœ… Step 1 β€” Initialize

terraform init
Enter fullscreen mode Exit fullscreen mode

βœ… Step 2 β€” Apply

terraform apply
Enter fullscreen mode Exit fullscreen mode

βœ… Step 3 β€” Open browser

Use output:

terraform output url
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Open in browser
πŸ‘‰ You will see:

Hello from Terraform User Data!
Enter fullscreen mode Exit fullscreen mode

πŸ”₯ 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
Enter fullscreen mode Exit fullscreen mode

OR change:

user_data_replace_on_change = true
Enter fullscreen mode Exit fullscreen mode

πŸ”₯ Bonus (VERY IMPORTANT FOR INTERVIEW)

Add this:

user_data_replace_on_change = true
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ 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)