{"id":580,"date":"2024-11-28T08:24:00","date_gmt":"2024-11-28T08:24:00","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=580"},"modified":"2024-11-28T08:24:00","modified_gmt":"2024-11-28T08:24:00","slug":"terraform-aws-vpc","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=580","title":{"rendered":"How to Create AWS VPC Using Terraform (Tutorial With Code)"},"content":{"rendered":"<p>In this blog, you will learn to create AWS VPC using well structure terraform modules. It is a step by step guide for beginners with detailed information.<\/p><h2 id=\"prerequisites\"><strong>Prerequisites<\/strong><\/h2><p>To follow this guide you need to have the following.<\/p><ol><li>The latest Terraform binary is installed and configured in your system.<\/li><li><a href=\"https:\/\/devopscube.com\/install-configure-aws-cli-linux\/\">AWS CLI installed <\/a>and configured with a Valid AWS account with full permissions to create and manage AWS VPC service.<\/li><li>If you are using terraform on an ec2 instance, ensure you have a valid<a href=\"https:\/\/devopscube.com\/aws-iam-role-instance-profile\/\"> IAM role<\/a> attached to the instance with VPC provisioning permissions.<\/li><\/ol><h2 id=\"terraform-aws-vpc-code-repository\"><strong>Terraform AWS VPC Code<\/strong> Repository<\/h2><p>AWS VPC terraform code is part of the <a href=\"https:\/\/github.com\/techiescamp\/terraform-aws.git?ref=devopscube.com\" rel=\"noreferrer noopener\">terraform AWS<\/a> repository. Clone it to your workstation to follow the guide.<\/p><pre><code>git clone https:\/\/github.com\/techiescamp\/terraform-aws.git<\/code><\/pre><p>Fork and clone the repository if you intend to reuse and make changes as per your requirements.<\/p><h2 id=\"terraform-aws-vpc-creation-workflow\">Terraform AWS VPC Creation Workflow<\/h2><p>The VPC terraform code is structured in the following way.<\/p><pre><code>\u251c\u2500\u2500 infra\n\u2502   \u2514\u2500\u2500 vpc\n\u2502       \u251c\u2500\u2500 main.tf\n\u2502       \u2514\u2500\u2500 variables.tf\n\u251c\u2500\u2500 modules\n\u2502   \u2514\u2500\u2500 vpc\n\u2502       \u251c\u2500\u2500 endpoint.tf\n\u2502       \u251c\u2500\u2500 internet-gateway.tf\n\u2502       \u251c\u2500\u2500 nacl.tf\n\u2502       \u251c\u2500\u2500 nat-gateway.tf\n\u2502       \u251c\u2500\u2500 outputs.tf\n\u2502       \u251c\u2500\u2500 route-tables.tf\n\u2502       \u251c\u2500\u2500 subnet.tf\n\u2502       \u251c\u2500\u2500 variables.tf\n\u2502       \u2514\u2500\u2500 vpc.tf\n\u2514\u2500\u2500 vars\n    \u2514\u2500\u2500 dev\n        \u2514\u2500\u2500 vpc.tfvars<\/code><\/pre><p><code><strong>vars<\/strong><\/code> folder contains the variables file named <code>vpc.tfvars<\/code> . It is the only file that needs modification<\/p><p>The <strong><code>modules\/vpc<\/code><\/strong> folder contains the following VPC related resources. All the resource provisioning logic is part of these resources.<\/p><ol><li>endpoint<\/li><li>internet-gateway<\/li><li>nacl<\/li><li>nat-gateway<\/li><li>route-tables<\/li><li>subnet<\/li><li>vpc<\/li><\/ol><p>The <strong><code>infra\/vpc\/main.tf<\/code><\/strong> file calls all the<code><strong> vpc<\/strong><\/code> module with all the VPC resources using the variables we pass using the <code>vpc.tfvars<\/code> file<\/p><h2 id=\"create-vpc-using-terraform\">Create VPC Using Terraform<\/h2><blockquote><strong>Note<\/strong>: The VPC and subnets for this demo is created based on our <a href=\"https:\/\/devopscube.com\/aws-vpc-design\/\" rel=\"noreferrer noopener\">VPC design document<\/a>. Please refer it if you want to understand how to design a VPC.<\/blockquote><p>We will be creating the VPC with the following<\/p>\n<!--kg-card-begin: html-->\n<ol class=\"wp-block-list is-style-cnvs-list-styled\">\n<li><strong>CIDR Block:&nbsp;<\/strong>10.0.0.0\/16<\/li>\n\n\n<li><strong>Region:<\/strong>&nbsp;us-west-2<\/li>\n\n\n<li><strong>Availability Zones:&nbsp;<\/strong>us-west-2a, us-west-2b, us-west-2c<\/li>\n\n\n<li><strong>Subnets<\/strong>: 15 Subnets (One per availability Zone)\n<ul class=\"wp-block-list\">\n<li>Public Sunets (3)<\/li>\n\n\n<li>App Subets (3)<\/li>\n\n\n<li>DB Subnets (3)<\/li>\n\n\n<li>Management Subnet (3) <\/li>\n\n\n<li>Platform Subnet (3)<\/li>\n<\/ul>\n<\/li>\n\n\n<li><strong>NAT Gateway<\/strong> for Private subnets<\/li>\n\n\n<li><strong>Internet Gateway<\/strong> for public subnets.<\/li>\n\n\n<li><strong>Enabled Endpoints:<\/strong>&nbsp;s3, Cloudwatch &amp; Secrets Manager<\/li>\n\n\n<li>Dedicated NACLs for 4 set of subnets.<\/li>\n<\/ol>\n<!--kg-card-end: html-->\n<p>Follow the steps give below to create VPC using Terraform code.<\/p><h3 id=\"step-1-cd-in-the-cloned-repository\">Step 1:  CD in the Cloned Repository<\/h3><p>If you haven&#8217;t already cloned the repo, clone it using the following command.<\/p><pre><code>git clone https:\/\/github.com\/techiescamp\/terraform-aws.git<\/code><\/pre><p>Then cd in to the terraform-aws folder<\/p><pre><code>cd terraform-aws<\/code><\/pre><h3 id=\"step-2-modify-the-vpctfvars\">Step 2:  Modify the vpc.tfvars<\/h3><blockquote><strong>Note<\/strong>: Open the repository folder in your favorite IDE, as it makes editing and reviewing the code easier.<\/blockquote><p>Modify the<strong><code> vars\/dev\/vpc.tfvars<\/code><\/strong> file as per your requirements.<\/p><p>If you dont want the NAT gateway, set <strong><code>create_nat_gateway<\/code><\/strong> to false.<\/p><pre><code>#vpc\nregion               = \"us-west-2\"\nvpc_cidr_block       = \"10.0.0.0\/16\"\ninstance_tenancy     = \"default\"\nenable_dns_support   = true\nenable_dns_hostnames = true\n\n#elastic ip\ndomain = \"vpc\"\n\n#nat-gateway\ncreate_nat_gateway = true\n\n#route-table\ndestination_cidr_block = \"0.0.0.0\/0\"\n\n#tags\nowner       = \"techiescamp\"\nenvironment = \"dev\"\ncost_center = \"techiescamp-commerce\"\napplication = \"ecommerce\"\n\n#subnet\n\nmap_public_ip_on_launch       = true\n\npublic_subnet_cidr_blocks     = [\"10.0.1.0\/24\", \"10.0.2.0\/24\", \"10.0.3.0\/24\"]\napp_subnet_cidr_blocks        = [\"10.0.4.0\/24\", \"10.0.5.0\/24\", \"10.0.6.0\/24\"]\ndb_subnet_cidr_blocks         = [\"10.0.7.0\/24\", \"10.0.8.0\/24\", \"10.0.9.0\/24\"]\nmanagement_subnet_cidr_blocks = [\"10.0.10.0\/24\", \"10.0.11.0\/24\", \"10.0.12.0\/24\"]\nplatform_subnet_cidr_blocks   = [\"10.0.13.0\/24\", \"10.0.14.0\/24\", \"10.0.15.0\/24\"]\navailability_zones            = [\"us-west-2a\", \"us-west-2b\", \"us-west-2c\"]\n\n#public nacl\n\ningress_public_nacl_rule_no    = [100]\ningress_public_nacl_action     = [\"allow\"]\ningress_public_nacl_from_port  = [0]\ningress_public_nacl_to_port    = [0]\ningress_public_nacl_protocol   = [\"-1\"]\ningress_public_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\negress_public_nacl_rule_no    = [200]\negress_public_nacl_action     = [\"allow\"]\negress_public_nacl_from_port  = [0]\negress_public_nacl_to_port    = [0]\negress_public_nacl_protocol   = [\"-1\"]\negress_public_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\n#app nacl\n\ningress_app_nacl_rule_no    = [100]\ningress_app_nacl_action     = [\"allow\"]\ningress_app_nacl_from_port  = [0]\ningress_app_nacl_to_port    = [0]\ningress_app_nacl_protocol   = [\"-1\"]\ningress_app_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\negress_app_nacl_rule_no    = [200]\negress_app_nacl_action     = [\"allow\"]\negress_app_nacl_from_port  = [0]\negress_app_nacl_to_port    = [0]\negress_app_nacl_protocol   = [\"-1\"]\negress_app_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\n##db nacl\n\ningress_db_nacl_rule_no    = [100]\ningress_db_nacl_action     = [\"allow\"]\ningress_db_nacl_from_port  = [0]\ningress_db_nacl_to_port    = [0]\ningress_db_nacl_protocol   = [\"-1\"]\ningress_db_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\negress_db_nacl_rule_no    = [200]\negress_db_nacl_action     = [\"allow\"]\negress_db_nacl_from_port  = [0]\negress_db_nacl_to_port    = [0]\negress_db_nacl_protocol   = [\"-1\"]\negress_db_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\n##management nacl\n\ningress_management_nacl_rule_no    = [100]\ningress_management_nacl_action     = [\"allow\"]\ningress_management_nacl_from_port  = [0]\ningress_management_nacl_to_port    = [0]\ningress_management_nacl_protocol   = [\"-1\"]\ningress_management_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\negress_management_nacl_rule_no    = [200]\negress_management_nacl_action     = [\"allow\"]\negress_management_nacl_from_port  = [0]\negress_management_nacl_to_port    = [0]\negress_management_nacl_protocol   = [\"-1\"]\negress_management_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\n#platform nacl\n\ningress_platform_nacl_rule_no    = [100]\ningress_platform_nacl_action     = [\"allow\"]\ningress_platform_nacl_from_port  = [0]\ningress_platform_nacl_to_port    = [0]\ningress_platform_nacl_protocol   = [\"-1\"]\ningress_platform_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\negress_platform_nacl_rule_no    = [200]\negress_platform_nacl_action     = [\"allow\"]\negress_platform_nacl_from_port  = [0]\negress_platform_nacl_to_port    = [0]\negress_platform_nacl_protocol   = [\"-1\"]\negress_platform_nacl_cidr_block = [\"0.0.0.0\/0\"]\n\n#endpoint\n\ncreate_s3_endpoint              = true\ncreate_secrets_manager_endpoint = true\ncreate_cloudwatch_logs_endpoint = true<\/code><\/pre><h3 id=\"step-2-initialize-terraform-and-execute-the-plan\">Step 2: Initialize Terraform and Execute the Plan<\/h3><p>Now cd in to <strong>infra\/vpc<\/strong> folder and execute the terraform plan to validate the configurations.<\/p><pre><code>cd infra\/vpc<\/code><\/pre><p>Initialize Terraform<\/p><pre><code>terraform init<\/code><\/pre><p>Execute the plan<\/p><pre><code>terraform plan  -var-file=..\/..\/vars\/dev\/vpc.tfvars<\/code><\/pre><p>You should see an output with all the resources that will be created by terraform.<\/p><h3 id=\"step-3-create-vpc-with-terraform-apply\">Step 3: Create VPC With Terraform Apply<\/h3><p>Lets create the VPC and related resources using terraform apply.<\/p><pre><code>terraform apply  -var-file=..\/..\/vars\/dev\/vpc.tfvars<\/code><\/pre><h3 id=\"step-4-validate-vpc\">Step 4: Validate VPC<\/h3><p>Head over to the AWS Console the check the Resource Map of the VPC.<\/p><p>Click on the created VPC and scroll down to view the Resource Map.<\/p><p>You should see 15 subnets , 6 route tables, internet gateway and NAT gateway as shown beow.<\/p><figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-77-4.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"1006\" height=\"780\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-77-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-77-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-77-4.png 1006w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure><h3 id=\"step-5-cleanup-the-resources\">Step 5: Cleanup the Resources<\/h3><p>If you have created the VPC for learning purposes and wish to clean up the resources created by Terraform, execute the following command<\/p><pre><code>terraform destroy  -var-file=..\/..\/vars\/dev\/vpc.tfvars<\/code><\/pre><h2 id=\"real-world-terraform-code-reference\">Real World Terraform Code Reference<\/h2><p>If you want to understand how Terraform code is structured and maintained in a real-world project environment, you should refer to the modernisation platform repository.<\/p><p>It contains code and standards that are actually used in the infrastructure management of the UK Ministry of Justice platform.<\/p><p>Refer to the<a href=\"https:\/\/github.com\/ministryofjustice\/modernisation-platform\/tree\/main\/architecture-decision-record?ref=devopscube.com\" rel=\"noreferrer noopener\"> architecture decision document<\/a> to understand the reasoning behind each design.<\/p><pre><code>https:\/\/github.com\/ministryofjustice\/modernisation-platform<\/code><\/pre><h2 id=\"conclusion\">Conclusion<\/h2><p>In this guide, we looked at creating<strong> aws VPC<\/strong> using terraform.<\/p><p>When implemented in real projects, you may need to consider more VPC options, like flow logs, peering connections, etc.<\/p><p>For state management, you should use <a href=\"https:\/\/devopscube.com\/setup-terraform-remote-state-s3-dynamodb\/\">remote backend with s3<\/a> with dynamoDB lock.<\/p><p>Also, tweak the Terraform code according to your requirements. If you want to gain more knowledge, go through each resource under the VPC module<\/p><p>If you face any errors or have any queries or suggestions, drop a comment below.<\/p>\n<hr><p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/terraform-aws-vpc\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Create AWS VPC Using Terraform (Tutorial With Code) \u2014 DevOpsCube<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/terraform-aws-vpc\/<\/p>\n","protected":false},"author":1,"featured_media":581,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-580","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=580"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/580\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/581"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}