{"id":23991742,"url":"https://github.com/jag-010/terraform-practice-project","last_synced_at":"2025-04-14T17:05:28.415Z","repository":{"id":195885759,"uuid":"481380936","full_name":"JAG-010/terraform-practice-project","owner":"JAG-010","description":"Learn Terraform with these projects","archived":false,"fork":false,"pushed_at":"2022-04-27T23:38:33.000Z","size":55,"stargazers_count":4,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-14T17:04:00.152Z","etag":null,"topics":["aws","projects","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JAG-010.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-04-13T21:36:02.000Z","updated_at":"2024-04-23T13:14:06.000Z","dependencies_parsed_at":"2023-09-20T01:00:57.033Z","dependency_job_id":"f91e34b6-ef1f-494d-9ec3-fc1b29cbe79c","html_url":"https://github.com/JAG-010/terraform-practice-project","commit_stats":null,"previous_names":["jag-010/terraform-practice-project"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAG-010%2Fterraform-practice-project","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAG-010%2Fterraform-practice-project/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAG-010%2Fterraform-practice-project/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JAG-010%2Fterraform-practice-project/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JAG-010","download_url":"https://codeload.github.com/JAG-010/terraform-practice-project/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248923766,"owners_count":21183952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","projects","terraform"],"created_at":"2025-01-07T19:59:50.770Z","updated_at":"2025-04-14T17:05:28.394Z","avatar_url":"https://github.com/JAG-010.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform project for beginners \n\u003e Learn Terraform by performing this small project \n\nLearn Terraform basics as you utilize Visual Studio Code (On Windows, Mac, or Linux!) to deploy AWS resources and an EC2 instance that you can SSH into to have your own re-deployable environment.\n\nIn this project we will learn how to\n\n- Create a VPC\n- Create EC2 instance\n- Install Docker in EC2\n\nall using terraform.  \n\n\nFollowing architecture diagram will be helpful to understand.\n\n![Architecture Diagram](TF_VPC-EC2.jpg)\n\nTo understand more about AWS networking [Click Here](https://awsmag.com/aws-networking-fundamentals/)\n\n**Topics**\n1. Setup Terraform and AWS\n2. Setup Project folder\n3. Create VPC\n4. Create EC2 instance\n\n\n## Setup Terraform and AWS\n\nAs a first step we need to have terraform installed and able to connect to AWS. Follow this [hashicorp](https://learn.hashicorp.com/tutorials/terraform/install-cli) document to install terraform on your PC/laptop.\n\n### AWS Credential Setup\n\nFirst, setup your AWS credentials locally by following the steps [here](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html)\n\nIf configured correct, you should be able to run a simple command such as `aws s3 ls` to list our your S3 buckets (*should return nothing if using an brand new empty account*). You can also view your configured credentials by running `cat ~/.aws/credentials`\n\n\n## Setup Project folder\n\nCreate a folder (*e.g `terraform-practice-project`*) to place the terraform files. Create a file named `main.tf` and open it on your favorite editor.\n\n## Create VPC\n\nBefore we start writing code to create VPC, we need to inform terraform about the cloud providers and versions which we are going to use. So create a file `provider.tf`\n\n\u003e  **Provider**\n\u003e \n\u003e Terraform relies on plugins called \"providers\" to interact with cloud providers, SaaS providers, and other APIs.\n\u003e Terraform configurations must declare which providers they require so that Terraform can install and use them. In the following code we have used AWS as provider. \n\n```\nterraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      version = \"~\u003e 3.0\"\n    }\n  }\n}\n\n// you can change your authentication system as per your needs\n// https://registry.terraform.io/providers/hashicorp/aws/latest/docs\nprovider \"aws\" {\n  region                  = \"us-east-2\"\n  shared_credentials_file = \"~/.aws/credentials\"\n  profile                 = \"personal\"\n}\n```\n\nNow lets create the VPC. Create a file `main.tf` and the following resource block.\n\n```\n// Create VPC\nresource \"aws_vpc\" \"lab_vpc\" {\n  cidr_block           = \"10.123.0.0/16\"\n  enable_dns_hostnames = true\n  enable_dns_support   = true\n\n  tags = {\n    Name = \"lab\"\n  }\n}\n```\n\nPublic Subnets are small pockets in each availability zone that can be accessed via the internet directly, Add this subnet block on the `main.tf`\n\n```\nresource \"aws_subnet\" \"lab_public_subnet\" {\n  vpc_id                  = aws_vpc.lab_vpc.id\n  cidr_block              = \"10.123.1.0/24\"\n  map_public_ip_on_launch = true\n  availability_zone       = \"us-east-2a\"\n\n  tags = {\n    Name = \"lab-public\"\n  }\n}\n```\n\nOur EC2 instance need to talk to internet, so we will add a Internet Gateway to our VPC\n\n```JSON\nresource \"aws_internet_gateway\" \"lab_igw\" {\n  vpc_id = aws_vpc.lab_vpc.id\n\n  tags = {\n    Name = \"lab-igw\"\n  }\n}\n```\n\nNow create a route table and associate the subnet to IGW \n\n```\nresource \"aws_route_table\" \"lab_public_route_table\" {\n  vpc_id = aws_vpc.lab_vpc.id\n\n  tags = {\n    Name = \"lab-rt\"\n  }\n}\n\nresource \"aws_route\" \"default_route\" {\n  route_table_id         = aws_route_table.lab_public_route_table.id\n  destination_cidr_block = \"0.0.0.0/0\"\n  gateway_id             = aws_internet_gateway.lab_igw.id\n}\n\nresource \"aws_route_table_association\" \"lab_public_assoc\" {\n  subnet_id      = aws_subnet.lab_public_subnet.id\n  route_table_id = aws_route_table.lab_public_route_table.id\n}\n```\n\ncreate a security group to allow access to our EC2 instance.\n\n```\nresource \"aws_security_group\" \"lab_sg\" {\n  name        = \"dev-sg\"\n  description = \"dev security group\"\n  vpc_id      = aws_vpc.lab_vpc.id\n\n  ingress {\n    from_port   = 0\n    to_port     = 0\n    protocol    = \"-1\"\n    cidr_blocks = [\"0.0.0.0/0\"] // This will allow access to public. Changing to your PC/Laptop public IP is recommended.\n  }\n\n  egress {\n    from_port   = 0\n    to_port     = 0\n    protocol    = \"-1\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n}\n```\n\n## Create EC2 instance\n\nWe have written terraform to create VPC, now lets work on creating a EC2 instance withing that VPC. \n\nConsidering our AWS account is new so we will create a new key-pair. If need more information on creating a key-pair on your Windows [Click Here](https://phoenixnap.com/kb/generate-ssh-key-windows-10)\n\n```\nresource \"aws_key_pair\" \"lab_auth\" {\n  key_name   = \"labkey\"\n  public_key = file(\"~/.ssh/labkey.pub\")\n}\n```\n\nwe want an EC2 instance with following configuration\n\n- Instance Type = t2.micro\n- OS = Ubuntu 18.04 \n- software installed = Docker\n\nsince we alway want to use the latest AMI, we will create a data block to pull the latest AMI details. \n\n\u003e **Data sources** allow Terraform to use information defined outside of Terraform, defined by another separate Terraform configuration, or modified by functions.\n\n```\ndata \"aws_ami\" \"server_ami\" {\n  most_recent = true\n  owners      = [\"099720109477\"] // ubuntu\n\n  filter {\n    name   = \"name\"\n    values = [\"ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*\"]\n  }\n}\n```\nwe will map this datasource to the ec2 resource block\n\nOne of the other requirement is to install Docker when the EC2 instance was provisioned. To achieve this we need to write a user data block as a template \n\nCreate a `userdata.tpl` file enter this bash script.\n```sh\n#!/bin/bash\nsudo apt-get update -y \u0026\u0026\nsudo apt-get install -y \\\napt-transport-https \\\nca-certificates \\\ncurl \\\ngnupg-agent \\\nsoftware-properties-common \u0026\u0026\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - \u0026\u0026\nsudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" \u0026\u0026\nsudo apt-get update -y \u0026\u0026\nsudo apt-get install docker-ce docker-ce-cli containerd.io -y \u0026\u0026\nsudo usermod -aG docker ubuntu\n```\n\nfinally lets create the EC2 instance. withing the `main.tf` add the ec2 resource block.\n\n```\n// Create EC2 instance\nresource \"aws_instance\" \"lab_node\" {\n  instance_type          = \"t2.micro\"\n  ami                    = data.aws_ami.server_ami.id\n  key_name               = aws_key_pair.lab_auth.id\n  vpc_security_group_ids = [aws_security_group.lab_sg.id]\n  subnet_id              = aws_subnet.lab_public_subnet.id\n  user_data              = file(\"userdata.tpl\")\n\n  root_block_device {\n    volume_size = 10\n  }\n\n  tags = {\n    Name = \"lab-node\"\n  }\n\n// below mentioned block will create a VSCode config file, which will provide ec2 access to vscode\n// this is OPTIONAL\n  provisioner \"local-exec\" {\n    command = templatefile(\"${var.host_os}-ssh-config.tpl\", {\n      hostname     = self.public_ip\n      user         = \"ubuntu\"\n      identityfile = \"~/.ssh/labkey\"\n    })\n    // This script was default to Windows \n    // IF using linux/macos use\n    // terraform apply -var=\"host_os=linux\"\n    interpreter = var.host_os == \"windows\" ? [\"powershell\", \"-command\"] : [\"bash\", \"-c\"]\n  }\n\n}\n```\n\nOnce the EC2 instance is created we need to know the public IP to connect. So we will create a output block on `output.tf` file to print the public IP of EC2.\n\n```\noutput \"dev_public_ip\" {\n  value = aws_instance.lab_node.public_ip\n}\n```\n\nAlso create a `variable.tf` file if using the VSCode config file. (These are completely optional)\n```\nvariable \"host_os\" {\n  type    = string\n  default = \"windows\"\n}\n```\nand `windows-ssh-config.tpl` for vscode configure\n\n```\nadd-content -path '~\\.ssh\\config' -value @'\n\nHost ${hostname}\n    HostName ${hostname}\n    User ${user}\n    IdentityFile ${identityfile}\n'@\n```\n\nOK... enough writing code. Lets rollout\n\nInitialize terraform \n\n```\nterraform init\n```\n\nFormat your using \n\n```\nterraform fmt\n```\n\nat last lets plan and apply\n\n```\nterraform plan\n\nterraform apply\n```\n\nThis whole terraform code can be found at my [GitHub repo](https://github.com/JAG-010/terraform-practice-project)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjag-010%2Fterraform-practice-project","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjag-010%2Fterraform-practice-project","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjag-010%2Fterraform-practice-project/lists"}