Launching a VPC with Public & Private subnet & NAT Gateway in AWS using Terraform!

This blog will guide you to create a VPC &2 subnets in it, one is public & another one is private. Then WordPress ec2 instance will be created in the public subnet, & a MySQL instance in the Private subnet. The MySQL instance will only allow the WordPress instance to connect and that too only for the database. Therefore to do any updates in the MySQL instance, one more ec2 instance known as Bastion Host or Jump Box will be created to access the MySQL instance. For MySQL to connect to the Internet, a NAT Gateway is created in the public subnet. Multiple Security groups are also created in this complete process to provide optimal security!

Harshit Dawar
9 min readJul 17, 2020

Ever wondered about launching the whole infrastructure in just one command, yes, it seems to be impossible, but it is possible. In this blog, I will guide you to construct the complete Pipeline described in the Introduction section of this blog.

The future is really about automation, it is a fact, it can be proved even by looking in the daily life examples, each & every one of us desires the things which are automated. No one wants to wait for even a second, everyone requires the work to be completed in lightning-fast speed, which is not possible if the work is being done manually. Therefore to achieve lightning-fast speed, work has to done automatically.

Without automation, today’s world can’t survive, in the present situation almost every company uses automation. For example, consider banks, they send the messages for each transaction, that process is automated right, it is not done manually. There are tons of examples present like these, & I am sure that most of you are experiencing these examples in your daily life.

Prerequisite for this Pipeline to Implement

  • Some knowledge of AWS & Github.
  • It would be a plus point for you if you are having the knowledge of JSON, because, in this Pipeline, HCL (Hashi Configuration Language) has been used which is the native language for Terraform, & it is very similar to JSON.

Explanation of Terraform

It is a tool developed by HashiCorp. Link for it is given below:

It is a tool that has the capability to handle the multi-cloud setup. It is a standardized tool, i.e. we have to write the code in one language only, but it will be automatically used to interact with multiple clouds (technically known as Terraform Providers). Its providers are listed in its documentation, the link for the same is present above.

Terraform works on declarative language, i.e. we just have to tell it what has to be done, it will automatically look into the situation & do that thing for us.

Terraform is intelligent because of the plugins for each of the providers it has, using them as API, it can interact with any of its providers.

Now, you are having more than enough knowledge required for this Pipeline, let’s begin the explanation of the complete automation Pipeline of Terraform.

List of steps in the Pipeline

Steps in the Pipeline:

  1. Create a Provider for AWS.
  2. Create an AWS key pair.
  3. Create a VPC (Virtual Private Cloud in AWS).
  4. Create a Public Subnet with auto public IP Assignment enabled in custom VPC.
  5. Create a Private Subnet in customer VPC.
  6. Create an Internet Gateway for Instances in the public subnet to access the Internet.
  7. Create a routing table consisting of the information of Internet Gateway.
  8. Associate the routing table to the Public Subnet to provide the Internet Gateway address.
  9. Creating an Elastic IP for the NAT Gateway.
  10. Creating a NAT Gateway for MySQL instance to access the Internet (performing source NAT).
  11. Creating a route table for the Nat Gateway Access which has to be associated with MySQL Instance.
  12. Associating the above-created route table with MySQL instance.
  13. Create a Security Group for the WordPress instance, so that anyone in the outside world can access the instance by SSH.
  14. Create a Security Group for Mysql instance which allows database access to only those instances who are having the WordPress security group created in step 9.
  15. Creating a Security Group for the Bastion Host which allows anyone in the outside world to access the Bastion Host by SSH.
  16. Creating a Security Group for the MySQL Instance which allows only bastion host to connect & do the updates.
  17. Launch a Webserver Instance hosting WordPress in it.
  18. Launch a MySQL instance.
  19. Launch a Bastion Host.
  20. Remote access to bastion host & from there access MySQL remotely and perform configuration.
  21. Remote access to WordPress and perform some configuration.

Code of the End-to-End Pipeline

In this pipeline, its explanation for each of the part is present in the code shown below with the help of comments for each part.

Step 1: Creating a Provider for AWS!

Sample Code to create a provider for the Terraform!

Step 2: Creating an AWS keypair!

Code to create a Key Pair!
Key Pair created in AWS! [Image by Author]

Step 3: Create a VPC (Virtual Private Cloud in AWS)!

Code to create a VPC!
Custom VPC created in AWS! [Image by Author]

Step 4: Create a Public Subnet with auto public IP Assignment enabled in custom VPC!

Code to create Public Subnet!
Public Subnet created in AWS! [Image by Author]

Step 5: Create a Private Subnet in customer VPC!

Code to create the Private subnet!
Private subnet created! [Image by Author]

Step 6: Creating an Internet Gateway!

Code to create Internet Gateway!
Internet Gateway is created in AWS! [Image by Author]

Step 7: Create a routing table for Internet Gateway!

Code to create the route-table!
Route Table created in AWS! [Image by Author]

Step 8: Associate the routing table to the Public Subnet!

Code to associate the routing table to the Subnet!
Route Table Associated to Subnet! [Image by Author]

Step 9: Creating an Elastic IP for the NAT Gateway!

Code to create an Elastic IP!
Elastic IP created in AWS! [Image by Author]

Step 10: Creating a NAT Gateway!

Code to create a NAT Gateway!
NAT Gateway created in AWS! [Image by Author]

Step 11: Creating a Route Table for the NAT Gateway!

Code to create a route table for the Nat Gateway!
NAT Gateway route table created! [Image by Author]

Step 12: Associating the Route table for NAT Gateway to Public Subnet!

Code to Associate the Route Table to the Private subnet!
Route table associated with the Private Subnet! [Image by Author]

Step 13: Create a Security Group for the WordPress instance!

Code to create the Security Group for the WordPress!
Security group created! [Image by Author]

Step 14: Create a Security Group for Mysql instance!

The security group created below allows the access to the database only from the instances associated with the WordPress Security Board.

Code to create a security group for MySQL!
Security group created at AWS! [Image by Author]

Step 15: Creating a Security Group for the Bastion Host!

This security group will allow anyone in the world to access this instance through SSH.

Code to create the security group for Bastion Host!
Bastion Host Security Group Created! [Image by Author]

Step 16: Creating a Security Group for the MySQL Instance which allows only bastion host to connect & do the updates!

Code to create the MySQL Bastion Host Security Group!
SG created at AWS! [Image by Author]

Step 17: Launching a Webserver Instance hosting WordPress in it in public subnet!

Code to launch a WordPress Instance by the support of Apache Webserver!
Instance created at AWS! [Image by Author]

Step 18: Launching a MySQL instance in the private subnet!

Code to launch the MySQL instance!
Instance created at AWS! [Image by Author]

Step 19: Launching a Bastion Host instance in the public subnet!

Code to launch a Bastion Host!
Instance created at AWS! [Image by Author]

Step 20: Remote access to the bastion host, from there access MySQL remotely, & perform some configuration!

First of all, use the bastion host public IP and login to it using the key attached to it using SSH. Dummy command to be followed:

ssh -i <Bastion host login Key Path> <username>@<IP of the bastion Host>Note: Generally username of the amazon linux 2 is ec2-user

Now copy the key for MySQL instance from the local system to the bastion host.

scp -i <MySQL Login key pair path> <path of file to copy> <Path where to copy>Note: The path where you copying the file should be accessible by the user. In my case command looks like this:cp -i MyKeyFinal.pem MyKeyFinal.pem ec2-user@<Bastion host IP>:/home/ec2-user/

Now, you must be landed on the MySQL Instance. Now, we have to perform configuration in MySQL so that WordPress can access the database.

First of all, open the MySQL Database by running the command “mysql”. Now, create a database in it I created one with the name of wordpress, by using the command “create database wordpress;”.

Now, we have to grant all privileges on this database, and for that run the command given below:

grant all privileges on wordpress.* to "wordpressUser"@"%" identified by "wordpressPassword";Note: This command will set the username & passowrd for WordPress as "wordpressUser" & "wordpressPassword" respectively.

After this, these settings/privileges has to be made permanent & for that run the command “flush privileges;”, & exit from the MySQL.

Now, run the services of MySQL and make them permanent by the commands given below.

service mysqld start
chkconfig mysqld on
Note: The above will work in centos version <= 7 or any other equivalent Linux flavor. If any other version is used, then in some of them like RHEL 8, Amazon Linux 2, systemctl command will work.

Step 21: Remote access to WordPress and perform some final configuration to complete the setup!

This configuration will automatically configure WordPress to use MySQL by giving the host address & database access settings in the configuration file.

First of all, switch to the wordpress folder by running the command:

cd /var/www/html/wordpress/

Now, edit one file named “wp-config-sample.php” by using vim editor. In this file, 4 fields need editing, which are displayed in the below image. [I already edited them, you have to edit them according to your settings of the database name, database host Ip, etc.

Fields edited in the Wordpress File!

Now, you have to rename this file to “wp-config.php”, do the same by running the command given below.

mv wp-config-sample.php wp-config.php

Now, restart the services of the httpd (apache webserver) by running the command given below.

systemctl restart httpd

Now, you just have to type the public IP of the wordpress instance in the URL window of the browser followed by the “/wordpress”.

For example: 15.5.7.57/wordpress

WordPress setup Page! [Image by Author]
First Blog Published using WordPress! [Image by Author]

If the code shown till here is combined in one single file and been executed then it becomes the complete infrastructure as a code (IAAC).

This concludes our Pipeline!

Important Commands & Facts to run this code!

  • You should have Terraform installed in your system!
  • After copying this code in a file, save that file with the “.tf” extension.
  • Run “terraform init” command.
  • Then run “terraform apply” to create your complete infrastructure!
  • Finally, when your work is completed, destroy your environment with the command “terraform destroy”.

I hope my article explains each and everything related to the complete end-to-end Terraform Pipeline of launching custom VPC with utmost security measures along with the explanation of the code, its configuration & execution of code. Thank you so much for investing your time in reading my blog & boosting your knowledge!

--

--

Harshit Dawar

AIOPS Engineer, have a demonstrated history of delivering large and complex projects. 14x Globally Certified. Rare & authentic content publisher.