This repository contains two examples of creating AWS EC2 instances using Terraform. One example creates an instance without an SSH key pair, while the other sets up an instance with an SSH key pair for secure access.
- Common Configuration
- Folder Structure
- Scenarios
- How to Create SSH Keys
- Notes for Students
- Commands to Apply Configuration
- Cleanup
- Terraform Cheatsheet
Both examples share some common configuration blocks for Terraform setup and AWS provider. These are detailed below:
-
Terraform Block: Specifies the required provider and version.
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
-
Provider Block: Configures the AWS provider with the desired region.
provider "aws" { region = "us-east-1" }
These blocks are consistent across both examples and should be placed at the top of your Terraform configuration file.
.
├── ec2-without-keys
│ └── ec2_without_keys.tf
├── ec2
│ └── ec2_with_keys.tf
File: ec2-without-keys/ec2_without_keys.tf
This scenario creates an EC2 instance without an SSH key pair, which means you cannot directly SSH into the instance. It is useful for instances managed by other tools or used as part of an autoscaling group where no direct access is required.
- Resource Block: Creates an EC2 instance with a specific AMI and instance type.
resource "aws_instance" "web" { ami = "ami-0ac4dfaf1c5c0cce9" # Amazon Linux - us-east-1 instance_type = "t2.micro" }
- Simpler configuration as no SSH key management is required.
- No direct SSH access to the instance.
- Debugging and troubleshooting can be challenging without access.
File: ec2/ec2_with_keys.tf
This scenario creates an EC2 instance with an SSH key pair, allowing secure access to the instance. It also includes a security group to allow SSH traffic.
-
Key Pair Resource: Specifies the public key file for SSH access.
resource "aws_key_pair" "my_key" { key_name = "my-key" public_key = file("~/.ssh/id_rsa.pub") }
-
Security Group Resource: Configures security group to allow SSH traffic.
resource "aws_security_group" "allow_ssh" { name = "allow_ssh" description = "Allow SSH inbound traffic" ingress { from_port = 22 to_port = 22 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"] } }
-
EC2 Instance Resource: Links the key pair and security group.
resource "aws_instance" "web" { ami = "ami-0ac4dfaf1c5c0cce9" # Amazon Linux - us-east-1 instance_type = "t2.micro" key_name = aws_key_pair.my_key.key_name security_groups = [aws_security_group.allow_ssh.name] tags = { Name = "devops" } }
- Secure access to the instance via SSH.
- Easier debugging and troubleshooting.
- Allows interactive management of the instance if needed.
- Requires management of SSH keys (ensure keys are secure and not lost).
- Open a terminal on your local machine.
- Generate an SSH key pair using the following command:
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa
- Follow the prompts to set a passphrase or leave it empty for no passphrase.
- The public key will be saved in
~/.ssh/id_rsa.pub
. Use this file in the Terraform configuration.
- Without SSH Key Pair: Use this for instances in autoscaling groups, ephemeral workloads, or fully managed setups where direct access is unnecessary.
- With SSH Key Pair: Use this for development, testing, or any scenario where you need direct access to the instance.
- Always keep your SSH private keys secure and backed up.
- Restrict SSH access in the security group to trusted IP ranges instead of allowing access from
0.0.0.0/0
. - Use IAM roles for accessing AWS resources from the instance instead of embedding credentials.
- Navigate to the desired scenario folder:
cd ec2-without-keys # or cd ec2
- Initialize Terraform:
terraform init
- Plan the infrastructure:
terraform plan
- Apply the configuration:
terraform apply
- (Optional) SSH into the instance if you used the "with SSH key" configuration:
ssh -i ~/.ssh/id_rsa ec2-user@<INSTANCE_PUBLIC_IP>
To destroy the resources created by Terraform:
terraform destroy
Here are some commonly used Terraform commands:
- Initialize Terraform:
terraform init
- Check the plan before applying:
terraform plan
- Apply the configuration:
terraform apply
- Destroy infrastructure:
terraform destroy
- Format code:
terraform fmt
- Validate configuration:
terraform validate
- Show resource state:
terraform show
- List workspace:
terraform workspace list
- Switch workspace:
terraform workspace select <workspace_name>