Create an EC2 instance with VPC , Subnet & Security Group

Linu Bajy
3 min readJun 10, 2021

Hey all,

This article is all about create an instance and other resources and to remotely execute commands in the instance. I hope you are interested just as I was when I first did it.

Remote executing seems like something that requires too much technical knowledge but terraform makes remote execution so much easier. Here we use an SSH (Secure SHell )access to form a secure connection by making use of keys, which I have mentioned in my last story :)

Lets see the code for it

maint.tf
---------------------------------
// Declaring the variables. Since keys are highly confidential, we // just specify the define the variables in a credentials.tfvars
// file and called in main.tf file.
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "private_key_path" {}
variable "key_name" {}
variable "region" {
default = "us-east-1"
}
//AWS Cloud Platform
provider "aws" {
access_key = var.aws_access_key
secret_key = var.aws_secret_key
region = var.region
}

Creating an VPC

We create a VPC when we want a private part of the cloud computing such as AWS, Azure etc.

main.tf
----------------------------------
resource "aws_vpc" "vpc" {
cidr_block = "10.1.0.0/16"
enable_dns_hostnames = "true"
}

Creating a subnet

A subnet is a logical division of the VPC.

main.tf
----------------------------------
resource "aws_subnet" "subnet1" {
cidr_block = "10.1.0.0/24"
vpc_id = aws_vpc.vpc.id
map_public_ip_on_launch = "true"
}

Creating a Security Group

A security group over a VPC enables to accept or deny traffic into the VPC.

Ingress permits incoming requests and egress controls the outgoing requests.

By default, AWS creates an ALLOW ALL egress rule when creating a new Security Group inside of a VPC. When creating a new Security Group inside a VPC, Terraform will remove this default rule, and require you specifically re-create it if you desire that rule.

main.tf
-----------------------------------
resource "aws_security_group" "my_sg" {
name = "my_sg"
vpc_id = aws_vpc.vpc.id
//Accepts tcp requests from port 22 and 80ingress {
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"]
}}
Note: The "-1" in protocol enables all protocols. If that is the case, the from_port and to_port must be kept to 0.

Creating an instance

We create an EC2 instance and create an SSH connection to it and run commands on the remote system.

resource "aws_instance" "my_ec2" {
ami = "ami-042e3286809f5df03"
instance_type = "t2.micro"
subnet_id = aws_subnet.subnet1.id
vpc_security_group_ids = [aws_security_group.my_sg.id]
//The name of the key will be defined in a credentials.tfvars file for confidentialitykey_name = var.key_name//Creating an SSH connection connection {
type = "ssh"
host = self.public_ip
user = "ec2-user"
private_key = file(var.private_key_path)
}
*******************************************************************Note: The private_key_path must be the path where the private key is present.//provisioner is the keyword used for remote execution of a command or a set of commands. It can be done by running a script or taking inline commands(here)********************************************************************provisioner "remote-exec" {inline = [
"apt-get update"
"apt-get install nginx"
"sudo /etc/init.d/nginx start"
]
}
}
Note: We have run commands to get an nginx server started.

Output Variable to fetch public DNS

Since the public IP address is known only after creation, it is given out as output variable.

output "aws_instance_public_dns" {
value = aws_instance.my_ec2.public_dns
}

The ouput will display the public IP address from where we can access the remote system, which shows the default page for nginx which we have run from the local system! How cool is that!

--

--