<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tamunopriye Dagogo-George</title>
    <description>The latest articles on DEV Community by Tamunopriye Dagogo-George (@priye).</description>
    <link>https://dev.to/priye</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1150810%2F19277be9-5f7a-42c4-8d78-0370e45cae03.JPG</url>
      <title>DEV Community: Tamunopriye Dagogo-George</title>
      <link>https://dev.to/priye</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/priye"/>
    <language>en</language>
    <item>
      <title>Terraforming Your Data Infrastructure on AWS: A Hands on guide for Data Engineers</title>
      <dc:creator>Tamunopriye Dagogo-George</dc:creator>
      <pubDate>Thu, 07 Sep 2023 09:54:21 +0000</pubDate>
      <link>https://dev.to/priye/terraforming-your-data-infrastructure-on-aws-a-hands-on-guide-for-data-engineers-58e0</link>
      <guid>https://dev.to/priye/terraforming-your-data-infrastructure-on-aws-a-hands-on-guide-for-data-engineers-58e0</guid>
      <description>&lt;p&gt;In the constantly evolving world of Data Engineering, if you haven't come across Terraform by now, you might have been living under a rock :) &lt;/p&gt;

&lt;p&gt;Terraform was originally embraced by DevOps Engineers for deploying cloud infrastructure. However, as Data Engineers recognized the need to provision similar resources, it has gained widespread adoption in the field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Terraform?&lt;/strong&gt;&lt;br&gt;
Terraform is an open-source tool developed by &lt;a href="https://www.hashicorp.com/"&gt;HashiCorp&lt;/a&gt; used for defining and provisioning infrastructure using the Declarative Approach of HashiCorp Configuration Language (HCL).&lt;/p&gt;

&lt;p&gt;Terraform is used for Infrastructure as code. What does this mean? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure&lt;/strong&gt; are services like virtual servers, storage buckets, lambda functions, RDS, IAM policies and so on, commonly found on cloud providers such as Azure, AWS, GCP and Oracle. For this tutorial we will be focusing on AWS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as code&lt;/strong&gt; refers to the use of code - in this case HCL, to create and manage the above resources as opposed to manually configuring them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why do Data Enginners use Terraform?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAC&lt;/strong&gt;: Terraform allows data engineers to define their infrastructure, including servers, networks, and storage, in  code. This enables them to version control their infrastructure configurations, track changes over time, and easily reproduce environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloud Agnostic&lt;/strong&gt;: Terraform supports multiple cloud providers (e.g., AWS, Azure, Google Cloud) and even on-premises environments. Data engineers can use a consistent toolset regardless of their cloud provider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;: Terraform configurations can be shared and collaboratively developed by data engineering teams. Changes can be reviewed, and infrastructure can be modified with the approval of team members.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change Management&lt;/strong&gt;: Data engineers can implement changes to infrastructure in a controlled manner. Terraform's plan and apply workflow allows them to preview changes before applying them, reducing the risk of errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Management&lt;/strong&gt;: Terraform maintains a state file that keeps track of the current state of the infrastructure. This state file helps Terraform understand which resources are already provisioned and how they are configured, preventing unnecessary modifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Terraform can be integrated into continuous integration/continuous deployment (CI/CD) pipelines, allowing data engineers to automate the testing and deployment of infrastructure changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Control&lt;/strong&gt;: By defining infrastructure in code, data engineers can implement cost-saving strategies, such as automatically shutting down non-essential resources when not in use or optimizing resource sizes based on actual usage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Terraform Lifecycle&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xoxGsHBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgoizdxvw5cq7k13398m.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xoxGsHBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgoizdxvw5cq7k13398m.jpeg" alt="terraform lifecycle" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terraform's lifecycle consists of four stages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform init&lt;/strong&gt; to initialize Terraform environment and cloud provider plugins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform plan&lt;/strong&gt; to create and display execution plans of resources to be configured&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform apply&lt;/strong&gt; to execute the plan and create the resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform destroy&lt;/strong&gt; to delete the resources created in a specific terraform environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial you will learn how to provision and configure an EC2 instance, and an S3 bucket using terraform. Make sure you have a fully operational AWS account to proceed.&lt;br&gt;
You can access the tutorial's code by visiting the &lt;a href="https://github.com/priye-1/terraforming-data-infrastructure"&gt;Github repository&lt;/a&gt; provided for reference. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;br&gt;
This is a lengthy tutorial, particularly for those new to Terraform. Therefore, I recommend taking it step by step, pausing when needed, and avoiding any sense of being overwhelmed.&lt;/p&gt;

&lt;p&gt;Now that you get the tea lets dive in and get hands-on!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Terraform&lt;/strong&gt;&lt;br&gt;
To use terraform locally you need to have it installed.&lt;/p&gt;

&lt;p&gt;With the code editor of your choice, Terraform can be installed on Mac or Linux using a tool called &lt;a href="https://warrensbox.github.io/terraform-switcher/"&gt;Terraswitch&lt;/a&gt;. This enables you to switch between different terraform versions, just like pyenv.&lt;br&gt;
Otherwise, you can use Package managers; Homebrew for mac -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;wget for linux :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update &amp;amp;&amp;amp; sudo apt install terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;chocolatey for windows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choco install terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can go through the official &lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli"&gt;documentation &lt;/a&gt; for any step you need further clarifications on.&lt;/p&gt;

&lt;p&gt;After installation, run &lt;code&gt;terraform -version&lt;/code&gt; on your terminal to confirm installation. This should return the version of terraform installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hjtZ3ces--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tz9tpdmdacnac9kmkuvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hjtZ3ces--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tz9tpdmdacnac9kmkuvj.png" alt="Terraform version" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AWS Authentication - Generate new access&lt;/strong&gt;&lt;br&gt;
In order to authorise terraform on AWS, you need to achieve the following steps: &lt;br&gt;
&lt;strong&gt;a.&lt;/strong&gt;  Create a new IAM user with administrator access to get the AWS access key and AWS secret key.&lt;br&gt;
On the AWS console, search for &lt;code&gt;IAM&lt;/code&gt; services and then navigate to &lt;code&gt;Users&lt;/code&gt; ---&amp;gt; &lt;code&gt;Create user&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T3E3GWo4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxna25gey3kpjiek0ils.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T3E3GWo4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxna25gey3kpjiek0ils.png" alt="Create new user" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step is to set permission, for this you will click on &lt;code&gt;Attach policies directly&lt;/code&gt; then &lt;code&gt;Administrator access&lt;/code&gt; and then &lt;code&gt;next&lt;/code&gt; to create user&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--12vF0JxO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vw77cz2oz2glp3wqon7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--12vF0JxO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vw77cz2oz2glp3wqon7.png" alt="set permissions" width="800" height="328"&gt;&lt;/a&gt;&lt;br&gt;
Now that you have created a user, you can then get access keys for that user by navigating back to &lt;code&gt;users&lt;/code&gt; --&amp;gt; &lt;code&gt;security credentials&lt;/code&gt; --&amp;gt; &lt;code&gt;create access key&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;choose the &lt;code&gt;command line interface&lt;/code&gt; option, write a description and finally &lt;code&gt;create access key&lt;/code&gt;. You can download as CSV for future reference or just take note of the generated keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b.&lt;/strong&gt; Configure AWS cli with new creds for AWS Authentication.&lt;br&gt;
To download the AWS cli on Mac, Linux or Windows kindly follow &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After successful installation run &lt;code&gt;aws --version&lt;/code&gt; for confirmation and then &lt;code&gt;aws configure&lt;/code&gt;. This will prompt you to provide the Access code and Secret code copied from step (a).  &lt;/p&gt;

&lt;p&gt;Alternatively, you can also authenticate AWS using environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this is done, you are all set to use terraform on your aws account!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Terraform Core Concepts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;File Structure&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Terraform treats every configuration as a module and executes all configuration files that ends in the extension &lt;em&gt;.tf&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A typical file structure for a new module is:&lt;/p&gt;

&lt;p&gt;├─ README.md&lt;br&gt;
├─ main.tf&lt;br&gt;
├─ variables.tf&lt;br&gt;
├─ outputs.tf&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;main.tf&lt;/strong&gt; will contain the main set of configurations for your module. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;variables.tf&lt;/strong&gt; will contain the variable definitions for your module. When your module is used by others, the variables will be configured as arguments in the module block.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;outputs.tf&lt;/strong&gt; will contain the output definitions for your module. Module outputs are often used to pass information about the parts of your infrastructure defined by the module to other parts of your configuration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Executing a terraform configuration file creates other files to be aware of, and ensure that you don't distribute them as part of your module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;terraform.tfstate&lt;/strong&gt; and &lt;strong&gt;terraform.tfstate.backup&lt;/strong&gt;: These files contain your Terraform state, and is how Terraform keeps track of the relationship between your configuration and the infrastructure provisioned by it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.terraform&lt;/strong&gt;: This directory contains the modules and plugins used to provision your infrastructure. These files are specific to a specific instance of Terraform when provisioning infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;.terraform.lock.hcl&lt;/strong&gt;: This file maintains specific provider versions, ensuring consistency in Terraform configurations and preventing unintended updates. It enhances control and stability, critical for production environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Terraform Syntax&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
These are the most essential parts of terraform&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Providers&lt;/strong&gt;: To configure any infrastructure you need to first declare the provider so that Terraform can install and use them. Terraform relies on plugins called providers to interact with cloud providers, and other APIs.&lt;/p&gt;

&lt;p&gt;Terraform has a list of providers, such as AWS, Azure, GCP, etc. visit this &lt;a href="https://registry.terraform.io/browse/providers"&gt;documentation&lt;/a&gt; to know how other providers are used.&lt;/p&gt;

&lt;p&gt;An AWS provider is declared in a provider block by the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;  &lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-north-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;: Terraform uses resource blocks to define components of your infrastructure, such as virtual networks, compute instances, etc. &lt;br&gt;
Most Terraform providers have a number of different resources as documented &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
    &lt;th&gt;AWS Resource Type&lt;/th&gt;
    &lt;th&gt;AWS Infrastructure&lt;/th&gt;
&lt;tr&gt;
    &lt;td&gt;aws_instance&lt;/td&gt;
    &lt;td&gt;EC2 Instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
      &lt;td&gt;aws_security_group&lt;/td&gt;
      &lt;td&gt;Security Group&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To create a resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"resource_type"&lt;/span&gt; &lt;span class="s2"&gt;"custom_resource_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sample_attribute&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resource blocks declare a resource type and name. Together, the type and name forms a unique resource identifier (ID) in the format &lt;code&gt;resource_type.resource_name&lt;/code&gt;&lt;br&gt;
To display information about a resource as output, you have to reference the resource ID.&lt;/p&gt;

&lt;p&gt;Resource types always start with the provider name followed by an underscore, for example; &lt;code&gt;aws_instance&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables:&lt;/strong&gt; The general idea of variables in programming is also applied in Terraform. This allows you to parameterize your configurations and make them more flexible and reusable.&lt;/p&gt;

&lt;p&gt;Terraform variables can be set in different ways;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the variable.tf file&lt;/li&gt;
&lt;li&gt;Individually, with the -var command line option.&lt;/li&gt;
&lt;li&gt;In variable definitions (.tfvars) files, either specified on the command line or automatically loaded.&lt;/li&gt;
&lt;li&gt;As environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will be using the first option, by declaring a variable block with the syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"var_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"description of var"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that Terraform variables can be of data types - string, number, boolean, list, object, map, tuples, etc. &lt;/p&gt;

&lt;p&gt;The value can then be accessed from within expressions as &lt;code&gt;var.&amp;lt;NAME&amp;gt;&lt;/code&gt;, where &lt;code&gt;&amp;lt;NAME&amp;gt;&lt;/code&gt; matches the label given in the declaration block. For example;&lt;br&gt;
In &lt;code&gt;variables.tf&lt;/code&gt; we create a new variable called &lt;code&gt;user_information&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"user_information"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;main.tf&lt;/code&gt; we access the variable using &lt;code&gt;var.user_information&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"some_resource"&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_information&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_information&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Outputs:&lt;/strong&gt; Output values make information about your infrastructure available on the command line, and can expose information for other Terraform configurations to use. Output values are similar to return values in programming languages.&lt;/p&gt;

&lt;p&gt;Each output value exported by a module must be declared using an output block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_ip_addr"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resource_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;custom_resource_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attribute&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The label immediately after the &lt;code&gt;output&lt;/code&gt; keyword is the output name, which must be a valid identifier. &lt;/p&gt;

&lt;p&gt;Now that we have understood the syntax, let's provision our first AWS resource&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Creating an Ec2 instance&lt;/strong&gt;&lt;br&gt;
For our first example we want to create an EC2 instance that we can access on the web. This means that we need to know the public IP to which the server is hosted, and will therefore be creating outputs in the outputs.tf file&lt;/p&gt;

&lt;p&gt;To create an EC2 instance we need to declare a resource block that calls a resource named - &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance"&gt;aws_instance&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;From the documentation we can see the &lt;em&gt;argument references&lt;/em&gt;  of &lt;code&gt;aws_instance&lt;/code&gt; which points out different arguments needed to configure an instance. &lt;br&gt;
For this example we will define the following;&lt;br&gt;
&lt;strong&gt;a.&lt;/strong&gt; &lt;code&gt;user_data&lt;/code&gt; file. which serves as a method to perform some configurations on the EC2 instance during creation, such as setting the hostname, or installing a software package.&lt;br&gt;
&lt;strong&gt;b.&lt;/strong&gt; &lt;code&gt;ami&lt;/code&gt; ID which is a unique identifier for a specific Amazon Machine Image.&lt;br&gt;
&lt;strong&gt;c.&lt;/strong&gt; &lt;code&gt;security_group&lt;/code&gt; to create a virtual firewall that controls inbound and outbound network traffic to Amazon EC2 instances.&lt;br&gt;
&lt;strong&gt;d.&lt;/strong&gt; &lt;code&gt;instance_type&lt;/code&gt; to define the hardware of the virtual machine, specifying its CPU, memory, storage capacity, and so on.&lt;br&gt;
&lt;strong&gt;e.&lt;/strong&gt; &lt;code&gt;key_name&lt;/code&gt; to specify the SSH keys required for secure access to an instance via SSH.&lt;/p&gt;

&lt;p&gt;Let's go ahead to create some of these as variables in &lt;code&gt;variables.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name of the EC2 instance"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"test_instance"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EC2 instance type"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_ami"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"id of AMI"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-065681da47fb4e433"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"key_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"key name"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ssh-keypair"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can obtain the &lt;code&gt;instance_type&lt;/code&gt; and &lt;code&gt;ami&lt;/code&gt; required to create the AWS instance by referencing the AWS console when manually setting up an EC2 instance.&lt;/p&gt;

&lt;p&gt;On your AWS portal search for &lt;code&gt;EC2&lt;/code&gt;, click on &lt;code&gt;instances&lt;/code&gt;, and then &lt;code&gt;launch instances&lt;/code&gt;&lt;br&gt;
On this page you can view the AMI id and instance type of your choice. Since we are using a free tier, &lt;em&gt;t3.micro&lt;/em&gt; is good enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jQyMyUWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k918yxlj4ser01gxvex0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jQyMyUWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k918yxlj4ser01gxvex0.png" alt="Instance type" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we will use these variables in &lt;code&gt;main.tf&lt;/code&gt; by declaring the provider and resource block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eu-north-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"web_traffic"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"allow_tls"&lt;/span&gt;

    &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;from_port&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
        &lt;span class="nx"&gt;to_port&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;from_port&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
        &lt;span class="nx"&gt;to_port&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
        &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_key_pair"&lt;/span&gt; &lt;span class="s2"&gt;"ssh_key_pair"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;key_name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_name&lt;/span&gt;
  &lt;span class="nx"&gt;public_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".ssh/rsa.pub"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"my_ec2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_ami&lt;/span&gt;
    &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_type&lt;/span&gt;
    &lt;span class="nx"&gt;user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"startup.sh"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;key_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_key_pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ssh_key_pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_name&lt;/span&gt;
    &lt;span class="nx"&gt;security_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web_traffic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we specified three resources; &lt;code&gt;aws_instance&lt;/code&gt;, &lt;code&gt;aws_key_pair&lt;/code&gt;, and &lt;code&gt;aws_security_group&lt;/code&gt;. &lt;br&gt;
Attributes of aws_security_group and aws_key_pair were parsed as arguments into aws_instance as &lt;code&gt;key_name&lt;/code&gt; and &lt;code&gt;security_groups&lt;/code&gt;. Note how we used the format &lt;code&gt;resource_type.resource_name.attribute&lt;/code&gt; to access them.&lt;/p&gt;

&lt;p&gt;Creating key pairs using &lt;code&gt;aws_key_pair&lt;/code&gt; allows you to securely connect to your EC2 instance using SSH while &lt;code&gt;aws_security_group&lt;/code&gt; allows you to configure inbound and outbound traffic using rules based on IP addresses, ports, and protocols. In this case we allowed traffic from any IP on ports 80 and 443.&lt;/p&gt;

&lt;p&gt;keep in view that to utilize &lt;code&gt;aws_key_pair&lt;/code&gt;, we must first generate an SSH key, which we can then provide to the AWS instance. To generate an SSH key with a length of 4096 bits,  run the command and follow the prompts. I created a &lt;code&gt;.ssh&lt;/code&gt; folder and an &lt;code&gt;rsa&lt;/code&gt; filename to store my keypair.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ssh-keygen command will generate two files: a private key file and a public key file. The private key file should be kept secure and never shared with anyone. The public key file can be shared with Amazon EC2 instances to allow SSH access.&lt;/p&gt;

&lt;p&gt;Thirdly, we declare the output block in &lt;code&gt;outputs.tf&lt;/code&gt; so that we can view the IP of the hosted server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;attribute_reference&lt;/em&gt; of the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance"&gt;documentation&lt;/a&gt; shows all the attributes that can be returned after provisioning a resource.&lt;/p&gt;

&lt;p&gt;Lastly, create a &lt;code&gt;startup.sh&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum update
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; httpd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start httpd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;httpd
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h1&amp;gt;Hello from Terraform&amp;lt;/h1&amp;gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /var/www/html/index.html]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the bash script that will be executed through &lt;code&gt;user_data&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that all requirements are in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Initialize the project  - &lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next to preview the changes that Terraform will make to your &lt;br&gt;
infrastructure, run &lt;code&gt;terraform plan&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ixs0Fyfh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ti5roz0vh73buhknkvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ixs0Fyfh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ti5roz0vh73buhknkvh.png" alt="tf apply" width="800" height="323"&gt;&lt;/a&gt;&lt;br&gt;
This will show you all the configurations to be deployed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally to apply the configurations, run &lt;code&gt;terraform apply&lt;/code&gt;&lt;br&gt;
This will output the public IP of the instance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QhWLi35z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iobc16ip3z1b4hsg0aax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QhWLi35z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iobc16ip3z1b4hsg0aax.png" alt="tf-apply" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Typing the IP address into your web browser with the format: &lt;code&gt;http://&amp;lt;IP_address&amp;gt;&lt;/code&gt; should yield the following page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dslU4sj2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b7gp2y43cl7xknyfctr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dslU4sj2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b7gp2y43cl7xknyfctr.png" alt="website" width="800" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and on your AWS console you will see the server up and running&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zjm1Jsfz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x907uhfl6f4thdm28pp2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zjm1Jsfz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x907uhfl6f4thdm28pp2.png" alt="Instance" width="800" height="27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! you have provisioned your first ec2 instance using terraform and you can ssh into the instance using the generated keypair with the command - &lt;code&gt;ssh -i "ssh-keypair.pem" ec2-user@ec2-&amp;lt;public_ip&amp;gt;.eu-north-1.compute.amazonaws.com.&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;5. Creating an S3 bucket&lt;/strong&gt;&lt;br&gt;
Now that we are familiar with the methods and syntax of terraform, this should be easy to grasp.&lt;/p&gt;

&lt;p&gt;To create a simple s3 bucket we will be using the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket"&gt;aws_s3_bucket&lt;/a&gt; resource.&lt;/p&gt;

&lt;p&gt;From the documentation linked above we can browse through  the &lt;em&gt;argument references&lt;/em&gt; to see what arguments we need to pass to this resource. &lt;br&gt;
Let's go ahead to define the &lt;code&gt;bucket_name&lt;/code&gt; in &lt;code&gt;variables.tf&lt;/code&gt;. Make sure to use a unique name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name of s3 bucke"&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tf-test-bucket-priye"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will add the aws_s3_bucket resource to &lt;code&gt;main.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_s3_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_name&lt;/span&gt;

    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My bucket"&lt;/span&gt;
        &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now run terraform &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt;. This will add an additional resource&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JOfkaKjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ttc7bircy5n6gpwnk4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JOfkaKjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ttc7bircy5n6gpwnk4m.png" alt="tf s3 apply" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also confirm the s3 bucket on your AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8GkK-uAv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vec613p1syq6ft5o042n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8GkK-uAv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vec613p1syq6ft5o042n.png" alt="bucket" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Destroy all resources&lt;/strong&gt;&lt;br&gt;
To remove all provisioned resources and reduce operational costs, execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! We have come to the end of this tutorial and you have taken your first steps into the world of Terraform!🎉&lt;/p&gt;

&lt;p&gt;In this tutorial, you've learned the fundamentals of Terraform, from setting up your environment to creating your first resources. But remember, Terraform is a vast and flexible tool with many advanced features waiting for you to explore. &lt;br&gt;
As you embark on your data engineering journey with Terraform, delve into advanced topics such as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modules:&lt;/strong&gt; Learn how to encapsulate and reuse your infrastructure code for better organization and maintainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic Blocks:&lt;/strong&gt; Discover how to create dynamic and flexible configurations for resources using dynamic blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Each:&lt;/strong&gt; Explore how to loop through lists and maps to create multiple similar resources with ease.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider Configuration:&lt;/strong&gt; Extend your skills by configuring different providers for hybrid and multi-cloud setups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State Management:&lt;/strong&gt; Master the art of state files, remote backends, and locking mechanisms for safe and efficient collaboration.&lt;/p&gt;

&lt;p&gt;If you enjoyed learning a thing or two from this tutorial, please consider sharing it. Additionally, if you'd be interested in a follow-up tutorial covering these advanced concepts, don't hesitate to express your interest in the comments below. Your feedback is highly appreciated!&lt;/p&gt;

&lt;p&gt;Happy Terraforming! 🌍💻&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
