Power of Terraform

Power of Terraform

I was recently approached by the sales team to explain the benefits of the cloud and, more importantly, why automation is such a game-changer. It struck me that the concept of DevOps still isn’t fully understood by everyone.

To put things into perspective, I remembered how, back in the day, setting up a LAMP stack (Apache, MySQL, PHP) could easily take an entire day—especially if you were dealing with more challenging Linux distributions like Gentoo. Fast forward to today: thanks to tools like Terraform and platforms like AWS, that same setup can now be done in mere minutes.

But enough theory—let’s get practical. Below is the code that demonstrates the power of automation. This script will:

  1. Create a VPC
  2. Set up subnets
  3. Add an Internet Gateway (IGW)
  4. Configure security groups
  5. Provision an RDS instance
  6. Deploy an Ubuntu VM and configure it to present data from a database on a simple webpage.

The speed and reliability that automation brings not only save time but also redefine how teams approach infrastructure and operations.

Please note this is a simple demo and does not goes in depth with security or containers. ( maybe in another episode)
NB: for obvious reasons please use more complex passwords



resource "aws_vpc" "demo_vpc" {
  cidr_block = "10.100.0.0/16"
}

resource "aws_subnet" "demo_subnet_a" {
  vpc_id            = aws_vpc.demo_vpc.id
  cidr_block        = "10.100.1.0/24"
  availability_zone = "eu-central-1a"
  map_public_ip_on_launch = true
}

resource "aws_subnet" "demo_subnet_b" {
  vpc_id            = aws_vpc.demo_vpc.id
  cidr_block        = "10.100.2.0/24"
  availability_zone = "eu-central-1b"
  map_public_ip_on_launch = true
}

resource "aws_security_group" "demo_sg" {
  vpc_id = aws_vpc.demo_vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

    ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["10.100.0.0/16"] # Allow DB access from within the VPC
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_db_subnet_group" "demo_subnet_group" {
  name       = "demo-subnet-group"
  subnet_ids = [
    aws_subnet.demo_subnet_a.id,
    aws_subnet.demo_subnet_b.id
  ]
}


# Create an Internet Gateway
resource "aws_internet_gateway" "demo_igw" {
  vpc_id = aws_vpc.demo_vpc.id
}

# Create a Route Table for the VPC
resource "aws_route_table" "demo_route_table" {
  vpc_id = aws_vpc.demo_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.demo_igw.id
  }
}

# Associate the Route Table with the Subnets
resource "aws_route_table_association" "demo_subnet_a" {
  subnet_id      = aws_subnet.demo_subnet_a.id
  route_table_id = aws_route_table.demo_route_table.id
}

resource "aws_route_table_association" "demo_subnet_b" {
  subnet_id      = aws_subnet.demo_subnet_b.id
  route_table_id = aws_route_table.demo_route_table.id
}

resource "aws_db_instance" "demo_rds" {
  allocated_storage    = 20
  engine               = "mysql"
  engine_version       = "8.0.39" # Replace with a supported version
  instance_class       = "db.t3.micro" # Use a valid instance class
  username             = "root"
  password             = "password123"
  publicly_accessible  = false
  vpc_security_group_ids = [aws_security_group.demo_sg.id]
  db_subnet_group_name = aws_db_subnet_group.demo_subnet_group.name
  skip_final_snapshot  = true
}

resource "aws_instance" "demo_vm" {
  ami           = "ami-0745b7d4092315796" # Ubuntu 22.04 AMI for us-east-1
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.demo_subnet_a.id
  vpc_security_group_ids = [aws_security_group.demo_sg.id]
  associate_public_ip_address = true

  user_data = <<-EOF
    #!/bin/bash
    # Update package lists and install necessary packages
    apt-get update -y
    apt-get install -y apache2 php mysql-client php-mysql
    RDS_HOST="`echo ${aws_db_instance.demo_rds.endpoint} | cut -d ':' -f 1`"

    # Enable and start Apache
    systemctl enable apache2
    systemctl start apache2

    # Create and populate the table
    mysql -h "$RDS_HOST" -u root -p'password123' -e "
    CREATE DATABASE demo_db;
    USE demo_db;
    CREATE TABLE demo_table (id INT AUTO_INCREMENT PRIMARY KEY, value VARCHAR(255));
    INSERT INTO demo_table (value) VALUES ('-- World --');
    "

    # Create sample PHP application
    cat < /var/www/html/index.php
    <!--?php \$conn = new mysqli('${aws_db_instance.demo_rds.endpoint}', 'root', 'password123', 'demo_db'); if (\$conn->connect_error) { die('Connection failed: ' . \$conn->connect_error); }
    \$result = \$conn->query('SELECT value FROM demo_table LIMIT 1');
    if (\$result->num_rows > 0) {
      while(\$row = \$result->fetch_assoc()) { echo '</p>
<h2><center>Hello ' . \$row['value']; echo '</h2>
<p></center>'; }
    } else { echo 'No data found'; }
    \$conn->close();
    ?-->
    EOT

    # Adjust permissions
    chown -R www-data:www-data /var/www/html
    chmod -R 755 /var/www/html
    rm /var/www/html/index.html
  EOF

  tags = {
    Name = "Demo-VM"
  }
}

output "ec2_public_ip" {
  value = aws_instance.demo_vm.public_ip
}

output "rds_endpoint" {
  value = aws_db_instance.demo_rds.endpoint
}


Leave a Reply

Your email address will not be published. Required fields are marked *