In the world of modern cloud computing, managing infrastructure manually is a thing of the past. Terraform allows you to treat your infrastructure as code, making it versionable, repeatable, and scalable.
In this guide, we'll walk through a complete Terraform project that sets up a secure web server on AWS.
The Project Structure
To follow along, you'll need the following files in your project directory:
provider.tf: Defines the cloud provider.variables.tf: Declares input variables.terraform.tfvars: Provides values for those variables.keypair.tf: Configures SSH access.security-group.tf: Defines firewall rules.main.tf: The core resource configuration.setup.sh: A startup script for the web server.outputs.tf: Displays important information after deployment.
1. Setting Up the Foundation
provider.tf
First, we tell Terraform to use the AWS provider and specify our target region.
provider "aws" {
region = var.region
}
variables.tf & terraform.tfvars
Variables keep our code flexible. We define them in variables.tf and provide specific values in terraform.tfvars.
variables.tf:
variable "region" { default = "eu-north-1" }
variable "instance_type" { default = "t3.micro" }
variable "ami" { description = "AMI ID" }
variable "key_name" { default = "my-key" }
terraform.tfvars:
ami = "ami-0aaa636894689fa47"
2. Security and Access
keypair.tf
To SSH into our instance, we need a key pair. This resource uploads your local public key to AWS.
resource "aws_key_pair" "deployer" {
key_name = var.key_name
public_key = file("~/.ssh/id_rsa.pub")
}
security-group.tf
We need to open ports 22 (SSH) and 80 (HTTP) to access our server.
resource "aws_security_group" "ec2_sg" {
name = "ec2_sg"
description = "Allow SSH and HTTP access"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
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"]
}
}
3. The Core Resource: EC2 Instance
main.tf
This is where everything comes together. We use the variables, the key pair, and the security group to launch our instance.
resource "aws_instance" "my_ec2" {
ami = var.ami
instance_type = var.instance_type
key_name = aws_key_pair.deployer.key_name
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
tags = { Name = "MyTerraformEC2" }
user_data = file("setup.sh") # Bootstrap the server!
}
setup.sh (User Data)
This script runs automatically when the instance starts. It installs Apache and a creative website template.
#!/bin/bash
yum update -y
yum install -y httpd wget unzip
systemctl start httpd
systemctl enable httpd
cd /tmp
wget https://www.tooplate.com/zip-templates/2156_graphite_creative.zip -O creative.zip
unzip creative.zip
cp -r 2156_graphite_creative/* /var/www/html/
chown -R apache:apache /var/www/html/*
rm -rf 2156_graphite_creative creative.zip
4. Getting Results
outputs.tf
After deployment, we want to know the public IP address of our server immediately.
output "public_ip" {
value = aws_instance.my_ec2.public_ip
}
How to Run This Project
- Prerequisites: Ensure you have the AWS CLI configured and an SSH key pair generated (
~/.ssh/id_rsa.pub). - Initialize: Run
terraform initto download providers. - Plan: Run
terraform planto see the proposed changes. - Apply: Run
terraform applyto deploy the infrastructure.
Once finished, copy the public_ip from the output, paste it into your browser, and enjoy your new website!
Conclusion
You've just deployed a full web infrastructure using Terraform! By splitting the configuration into logical files, you've created a project that is easy to read, maintain, and share.
Happy Coding!