DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

Terraform Provisioners

๐ŸŽฏ Lab Goal

You will:

  • Create an EC2 instance
  • Install NGINX using remote-exec
  • Save EC2 IP locally using local-exec
  • Upload a file using file provisioner
  • Verify everything in browser

๐Ÿงฑ STEP 1 โ€” Prerequisites (VERY IMPORTANT)

โœ… You must have:

  • AWS account
  • Terraform installed
  • Key pair created in AWS:

    • Name: terraform-key
    • Download: terraform-key.pem

โœ… Place file in your project:

provisioner-lab/
  main.tf
  terraform-key.pem
  index.html
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฑ STEP 2 โ€” Fix Key Permissions (Mac/Linux)

chmod 400 terraform-key.pem
Enter fullscreen mode Exit fullscreen mode

โ— If you skip โ†’ SSH WILL FAIL


๐Ÿงฑ STEP 3 โ€” Create index.html (file provisioner test)

๐Ÿ“„ index.html

<h1>Welcome from Terraform Provisioner Lab</h1>
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฑ STEP 4 โ€” Security Group (AWS Console)

Allow:

Type Port Source
SSH 22 0.0.0.0/0
HTTP 80 0.0.0.0/0

Copy Security Group ID:

sg-xxxxxxxx
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฑ STEP 5 โ€” Full Terraform Code

๐Ÿ“„ main.tf

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "web" {
  ami           = "ami-0c02fb55956c7d316" # Amazon Linux 2
  instance_type = "t2.micro"

  key_name = "terraform-key"

  vpc_security_group_ids = ["sg-xxxxxxxx"] # replace

  # โœ… FILE PROVISIONER (upload HTML)
  provisioner "file" {
    source      = "index.html"
    destination = "/home/ec2-user/index.html"

    connection {
      type        = "ssh"
      user        = "ec2-user"
      private_key = file("terraform-key.pem")
      host        = self.public_ip
    }
  }

  # โœ… REMOTE-EXEC (install nginx + deploy page)
  provisioner "remote-exec" {
    inline = [
      "sudo yum install nginx -y",
      "sudo systemctl start nginx",
      "sudo systemctl enable nginx",
      "sudo mv /home/ec2-user/index.html /usr/share/nginx/html/index.html"
    ]

    connection {
      type        = "ssh"
      user        = "ec2-user"
      private_key = file("terraform-key.pem")
      host        = self.public_ip
    }
  }

  # โœ… LOCAL-EXEC (save IP locally)
  provisioner "local-exec" {
    command = "echo ${self.public_ip} > public_ip.txt"
  }

  tags = {
    Name = "provisioner-lab"
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช STEP 6 โ€” Run Terraform

terraform init
terraform apply -auto-approve
Enter fullscreen mode Exit fullscreen mode

โš™๏ธ WHAT HAPPENS INTERNALLY

  1. EC2 instance created
  2. Terraform connects via SSH
  3. File provisioner uploads HTML
  4. Remote-exec installs nginx
  5. HTML moved to nginx folder
  6. local-exec saves IP to file

๐Ÿ” STEP 7 โ€” VERIFY

โœ… Check local file

cat public_ip.txt
Enter fullscreen mode Exit fullscreen mode

Example:

3.145.23.10
Enter fullscreen mode Exit fullscreen mode

โœ… Open browser

http://<EC2_PUBLIC_IP>
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ You should see:

Welcome from Terraform Provisioner Lab
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช STEP 8 โ€” TEST & BREAK (IMPORTANT FOR INTERVIEW)

โŒ Test 1: Wrong key

Change:

private_key = file("wrong.pem")
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Result:

  • SSH fails
  • Provisioning fails

โŒ Test 2: Remove port 22

๐Ÿ‘‰ Result:

  • Terraform hangs (waiting SSH)

โŒ Test 3: Remove sudo

๐Ÿ‘‰ Result:

  • Permission denied
  • NGINX not installed

๐Ÿ” STEP 9 โ€” DESTROY

terraform destroy -auto-approve
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  WHAT YOU LEARNED

Provisioners:

  • file โ†’ copy file
  • remote-exec โ†’ configure server
  • local-exec โ†’ run locally

Execution order:

  1. Create EC2
  2. file provisioner
  3. remote-exec
  4. local-exec

Key concepts:

  • self.public_ip
  • SSH connection block
  • Key permissions
  • Provisioner dependency on resource

๐ŸŽฏ REAL DEVOPS TIP (IMPORTANT)

๐Ÿ‘‰ In production, replace this with:

  • user_data (bootstrap)
  • Ansible (config)
  • Packer (pre-built AMI)

Top comments (0)