Terraform is an open-source infrastructure as code software tool created by HashiCorp. To use terraform, you define the resources you want to create using a declarative configuration language created by Hashicorp known as HashiCorp Configuration Language (HCL), or optionally JSON.
AWS is a popular cloud provider similar to Azure and GCP.
Also check
- Terraform AWS VPC with Public and Private subnets with NAT
- Using Terraform to Launch a VPS Instance in Digital Ocean
- Create an RDS instance in terraform with a Mariadb Example
- Using terraform to launch Digitaocean kubernetes cluster
- How to Create Aws Lightsail Instance With Terraform
Prerequisites
To follow along this guide, you need the following:
- AWS IAM credentials with permissions to manage EC2 instances – access key and secret key
- AWS cli installed in your system. Install it here if you don’t have
- Terraform installed in your machine, get terraform from (here)[https://www.terraform.io/downloads.html] if you don’t have it
This is the terraform version I am using:
➜ terraform --version
Terraform v1.0.7
on darwin_amd64
Export aws credentials in your terminal before proceeding.
export AWS_ACCESS_KEY_ID=your-key-id-here
export AWS_SECRET_ACCESS_KEY=youe-access-key-here
export AWS_DEFAULT_REGION=aws-region
Table of Content
- Adding Provider
- Defining Terraform Version
- Defining variables
- Creating Key Pair
- Creating EC2 instance
- Defining Security Group
- Defining outputs
- Final code
- Creating the resources
Adding a Provider
A Terraform Provider represents an integration that is responsible for understanding API interactions with the underlying infrastructure. The provider in our case defines connection to AWS. We also define that we want to provision resources in us-west-2
region.
provider "aws" {
region = "us-west-2"
}
Defining Terraform Version
Let us also define the version of terraform that we want to use. We define the terraform version to be any version above 1.0.7.
terraform {
required_version = ">= 1.0.7"
}
Defining variables
Input variables serve as parameters for a Terraform module, allowing aspects of the module to be customized without altering the module’s own source code, and allowing modules to be shared between different configurations.
In our case we define a key path for the ssh public key that we will use to ssh to the server.
variable "key_path" {
default = "~/.ssh/id_rsa.pub"
}
Defining Key Pair
Next, let’s create a public key resource that we can use to ssh to the server. Here we define key-pair my-pub-key
with the public key value of the variable defined in the variables.
resource "aws_key_pair" "my-pub-key" {
key_name = "my-pub-key"
public_key = file("${var.key_path}")
}
Creating EC2 instance
Next, we define the resource creating our ec2 instance. We have to specify the instance properties like the AMI, Instance type, SSH key to use, Security groups, Subnet to launch the instance in. We also define that the instance be associated with a public ip address so we can access from the outside.
Next we define a disk size and give the instance tags.
resource "aws_instance" "instance" {
ami = "ami-0ddb956ac6be95761"
instance_type = "t2.small"
key_name = aws_key_pair.my-pub-key.id
vpc_security_group_ids = [aws_security_group.sg.id]
subnet_id = "subnet-xxxxxxx"
associate_public_ip_address = true
root_block_device {
volume_size = 50
delete_on_termination = true
}
tags = {
Name = "Citizix-Debian-Server"
}
}
Defining Security Group
Next we define a security group. A security group acts as a virtual firewall for your EC2 instances to control incoming and outgoing traffic. We define rules in our security group outlining the traffic that we want to accept.
In our case, we want to have all outgoing traffic whitelisted and only allow incoming traffic from port 22.
resource "aws_security_group" "sg" {
name = "Citizix-Server-SG"
description = "Restrictions for Citizix server"
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"]
}
vpc_id = "vpc-xxxxxx"
tags = {
Name = "Citizix-Server-SG"
}
}
Defining outputs
Finally, we define outputs. Terraform output values allow you to export structured data about your resources. In our case, we can use outputs to export data about the instance we just created like the IP that it has been assignend.
output "instance-private-ip" {
value = aws_instance.instance.private_ip
}
output "instance-public-ip" {
value = aws_instance.instance.public_ip
}
Full Code
This is the full code for provisioning an ec2 instance in AWS.
provider "aws" {
region = "us-west-2"
}
terraform {
required_version = ">= 1.0.7"
}
variable "key_path" {
default = "~/.ssh/id_rsa.pub"
}
resource "aws_key_pair" "my-pub-key" {
key_name = "my-pub-key"
public_key = file("${var.key_path}")
}
resource "aws_instance" "instance" {
ami = "ami-0ddb956ac6be95761"
instance_type = "t2.small"
key_name = aws_key_pair.my-pub-key.id
vpc_security_group_ids = [aws_security_group.sg.id]
subnet_id = "subnet-xxxxxxx"
associate_public_ip_address = true
root_block_device {
volume_size = 50
delete_on_termination = true
}
tags = {
Name = "Citizix-Debian-Server"
}
}
resource "aws_security_group" "sg" {
name = "Citizix-Server-SG"
description = "Restrictions for Citizix server"
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"]
}
vpc_id = "vpc-xxxxxx"
tags = {
Name = "Citizix-Server-SG"
}
}
output "instance-private-ip" {
value = aws_instance.instance.private_ip
}
output "instance-public-ip" {
value = aws_instance.instance.public_ip
}
Creating resources
With all the full code in place, let us create the AWS resources.
terraform init
terraform plan
terraform apply
Conclusion
In this guide we managed to create an EC2 instance using terraform.
5 Comments
Pingback: Links 18/10/2021: Linux 5.15 RC6 and 7 New Stable Kernels | Techrights
Pingback: How to use terraform targets to run specific resource
Pingback: How to use Terraform to create a vpc network and a GKE in GCP
Pingback: How to Build an AWS EC2 Machine Images (AMI) With Packer
Pingback: How to Build an AWS EC2 Machine Images (AMI) With Packer