How to Create VPC and EC2 on AWS for Free Tier With Terraform
Tags: aws, terraform, cloud, instance
Published: 2024-04-03 19:58:38

## Overview

In this post, you will learn how to deploy resources to AWS without exceeding the free limits with Terraform.

Once you follow this tutorial, you will have:

- A VPC with `10.10.0.0/16` CIDR,
- A public subnet with `10.10.20.0/24` CIDR on `eu-central-1a` AZ,
    - A public subnet with `10.10.40.0/24` CIDR on `eu-central-1b` AZ,
    - A private subnet with `10.10.21.0/24` CIDR on `eu-central-1a` AZ,
    - A private subnet with `10.10.41.0/24` CIDR on `eu-central-1b` AZ,
    - Security groups for SSH, HTTP(S) for ingress and all for egress,
- A Public Elastic IP,
- An Ec2 Instance,
	- Ubuntu Linux 
    - `t2.micro` type,
    - 25GB storage,

All these resources are free if you are on AWS free tier!

You can see an example diagram of the resources.

  ![](https://cdn.jsdelivr.net/gh/burakberkkeskin/blog-cdn/how-to-create-vpc-ec2-on-aws-for-free-tier/general/resources-overview.excalidraw.png)
## Pre-Requirements

- An AWS account.
- A Linux or macOS computer to run Terraform.
- Git

## Install Terraform

You can skip this section if you already have Terraform installed on your computer.

If you are reading this tutorial, you know what Terraform is. Terraform is an open-source Infrastructure as Code (IaC) tool that enables users to define and provision infrastructure efficiently across various cloud providers.

### Installation on MacOS

If you have `Homebrew` installed on your computer, you can use `brew` to install Terraform.  
Open a terminal and run these commands:

```bash
brew tap hashicorp/tap && \
brew install hashicorp/tap/terraform
```

Once the installation is finished, you can check the Terraform version and verify the installation.

```bash
terraform --version
```

### Installation on Windows

You can head to the official [Terraform installation document](https://developer.hashicorp.com/terraform/install#windows) and download the latest Terraform version.

But my recommendation is to use Linux with WSL.

### Installation on Linux

You can head to the official [Terraform installation document](https://developer.hashicorp.com/terraform/install#linux) and click on the tab for your distro.

If you are using Arch Linux and have `yay` tool installed , you can simply install Terraform with the commands below.

```bash
yay -S terraform
```

## Create an AWS Service Account for Terraform

If you have a service account for the terraform, you can skip this step. 

To create a service account, you can follow the tutorial below step by step. 

{% embed https://burakberk.dev/how-to-create-a-service-account-on-aws-for-terraform/ %}

## Create an SSH Key For Linux Server Authentication

You can skip this section if you already have an SSH key to use on a Linux server.

To enhance Linux server security, generate an SSH key pair using the `ssh-keygen` command, enabling secure authentication by pairing a private key on the client with the server's authorized public key.

A SSH key pair consists of 2 files, public and private. You should keep the private one safe and secure. You can think that a private file opens the locks. You should use the public one to lock something like a Linux server.

In summer, we will use a public key to lock our server SSH on our Terraform configuration. After the server is up and running, we will use the private one to connect to the server.

To create a SSH key pair, you can use this command on your macOS or Linux computer.

- `-f ~/.ssh/aws-ec2`: The file path and name where you want to create the key pair.
- `-C "contact@burakberk.dev"`: The comment can be anything.
- Once you run the command below, it will ask you to enter a passphrase. This is password protection for the private file. You should use a secure and strong password.

```bash
ssh-keygen -t ed25519 -f ~/.ssh/aws-ec2 -C "contact@burakberk.dev" 
```

To view the private file that we will use to connect to the server, you can run:

```bash
cat ~/.ssh/aws-ec2 
```

To view the public file that we will use on Terraform, you can run:

```bash
cat ~/.ssh/aws-ec2.pub
```

## Create AWS Credentials Environment Variables

Since Terraform must be authenticated to your AWS account, we will use the access keys we created earlier.

There are multiple ways to use those keys. But in this tutorial, I will use the environment variables method, which is unsafe for the long term.  
For more details about AWS authentication, you can read the [AWS Terraform documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs).

We could run the `export` command below directly, but this will save the secret access keys in the shell history, which is very unsafe. So we will create a file and put the keys into it.

Create a file named `terraform-aws.sh` with `vim`

```bash
vim terraform-aws.sh
```

Copy this template and paste it into the file.

```bash
#!/bin/bash
export AWS_ACCESS_KEY_ID=YourAccessKeyId
export AWS_SECRET_ACCESS_KEY=YourSecretAccessKey
```

Press the `i` button, move the cursor with the arrow buttons on your keyboard, and edit the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` variables with yours.

Press `esc`, `colon (:)` and write `wq!` and hit `enter` on your keyboard to save the changes and exit the editor.

❗Keep this file safe and secure. Whoever gets access to the file controls all resources on your AWS account.

Now you can use this file to use your keys.

```bash
source terraform-aws.sh
```

📚Note: If you close your terminal or open a new one, you should run the `source` command each time before running `terraform` commands.  
If your AWS variables get lost and you run `terraform` commands, you will get an error, like in the example below:

```
Planning failed. Terraform encountered an error while generating this plan.

Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
```

## Download the Sample Terraform Files From Github

You should create a couple of files. Instead of creating them manually, you can just download them from the Github repository.

Open a terminal and change the directory to the home directory. You can choose anywhere you want.

```bash
cd $HOME
```

Then you can download the Terraform files from the Github repository.

```bash
git clone --depth 1 --branch blog-tutorial https://github.com/burakberkkeskin/personal_infra.git && \ 
cd personal_infra/main
```

Once the download is finished and you are in the Terraform configuration directory, you can run `terraform init` to see if Terraform configuration is ready to be used.

❗Be aware that you are in the `personal_infra/main` directory. The `terraform` commands below should also run in this directory too.   

```bash
terraform init
```

## Configure and Customize Terraform Variables

### Add the SSH Key

Print the public key you created earlier and copy it.

```bash
cat ~/.ssh/aws-ec2.pub
```

Open the `variables.auto.tfvars` file with a file editor.

```bash
vim variables.auto.tfvars
```

Press the `i` button, move to a new line with the arrow buttons on your keyboard, and create a new variable named `ec2_public_key` like in the example below:

```tf
// general variables
 project_name = "main"
 aws_region = "eu-central-1"
 aws_zone = "eu-central-1a"

 ec2_public_key = "ssh-ed25519 SuperSecretKeylZDI1NTE5AAAAINa3hu5qHgD3cS7dxMlO6I3dTTx/AFU5HqhNZnM6rnEJ contact@burakberk.dev"
 
 ...
```

Press `esc`, `colon (:)` and write `wq!` and hit `enter` on your keyboard to save the changes and exit the editor.

You can also configure other variables as you wish, like the `aws_region`, `project_name`.

## Terraform Plan

To see if everything is ready to use, you can run `terraform plan` command to see the resources that will be created.

```bash
terraform plan
```

If you see that there are resources that will be created as a plan, it means you have configured terraform correctly ✅

## Terraform Apply

Once you are ready to create the resources you saw in the `terraform plan` output, you can run `terraform apply` command.

```bash
terraform apply
```

It will ask you to be sure.

```bash
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
```

Write `yes` and hit enter. Within a few minutes, your resources will be ready to use.

```bash
Apply complete! Resources: 23 added, 0 changed, 0 destroyed.

Outputs:
ec2_instance_private_ip = "10.10.20.136"
ec2_instance_public_ip = "35.158.26.83"
```

To check from the AWS Console, you can head to the EC2 instance. You can also see the IP address of the instance.

![](https://cdn.jsdelivr.net/gh/burakberkkeskin/blog-cdn/how-to-create-vpc-ec2-on-aws-for-free-tier/ec2-details/1-ec2-details.png)

Ta da 🥳 Your Ubuntu Linux server is ready to use.

## SSH Into the Server For Testing

You have already seen the IP address of the instance. To connect, you can open a terminal and run `ssh` command:

- `-i ~/.ssh/safaws`: The path to the private SSH key.
- `ubuntu`: Default username of the Ubuntu AMI on the AWS.
- `35.158.26.83`: Public IPv4 address.

```bash
ssh -i ~/.ssh/safaws ubuntu@35.158.26.83
```

If it is the first time that you are connecting to a server, it will ask if you are sure to connect. Write `yes` enter hit Enter.

```bash
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
```

If you have followed the tutorial until now, congratulations, You are on the Linux server!

You can use this server however you like. For example, you can host a website, make it a VPN server, a database server, or anything else you want.

## Example Nginx Container

In this step, you will see how to deploy a nginx container. The docker should be already installed in the instance. All you need to do is run the `docker run` command.

Let's run a  Nginx container.

```bash
sudo docker run --name "website" --rm -d -p "80:80" nginx 
```

To test if everything works, you can simple open a browser and head to the public IPv4 address like:

```
http://35.158.26.83
```


## Destroying the All Resources

If you want to destroy all the resources for some reason, like the end of the free tier, you can destroy all resources easily.

First, you should change the directory to the Terraform you downloaded earlier.

```bash
cd ~/personal_infra/main
```

You should activate the AWS keys again for authentication.

```bash
source terraform-aws.sh
```

Now, it is time to destroy all resources.

```bash
terraform destroy
```

It will ask you to be sure. Write `yes` and hit Enter.

```bash
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
```

Once all resources are destroyed, you will see an output like below.

```bash
Destroy complete! Resources: 23 destroyed.
```

## Re-Use on Another Account

If you want to use the exact same configuration, you can just change the AWS access keys in the `terraform-aws.sh.` file and apply the same configuration. With that, you can change AWS accounts under 10 minutes!

## For More

If you like the post, you can head to my personal blog site and read more about DevOps, Linux, System Engineering!

{% embed https://burakberk.dev %}