<?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>The Ops Community ⚙️: Moses Itoya</title>
    <description>The latest articles on The Ops Community ⚙️ by Moses Itoya (@royalt1234).</description>
    <link>https://community.ops.io/royalt1234</link>
    <image>
      <url>https://community.ops.io/images/dKneUXrtHEgXgoW6_2JS-BbN06zbTXVZnAYC5yrSV8I/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL3Vz/ZXIvcHJvZmlsZV9p/bWFnZS83MjkvOWNl/YmE0OTQtODcxZS00/Y2RhLWFkNzYtNTg1/NTVjMTA0NDFlLmpw/ZWc</url>
      <title>The Ops Community ⚙️: Moses Itoya</title>
      <link>https://community.ops.io/royalt1234</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://community.ops.io/feed/royalt1234"/>
    <language>en</language>
    <item>
      <title>Terraform Modules - A High Level Overview</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Sun, 10 Jul 2022 09:10:06 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/terraform-modules-a-high-level-overview-421i</link>
      <guid>https://community.ops.io/royalt1234/terraform-modules-a-high-level-overview-421i</guid>
      <description>&lt;h2&gt;
  
  
  Topic Introduction
&lt;/h2&gt;

&lt;p&gt;IaC helps with better complexity management and a much better visibility into infrastructure configuration. &lt;strong&gt;Whichever IaC tool you are using, it's important to have a code that is easier to read and more understandable, especially if you are in a team environment.&lt;/strong&gt; This would ensure your code base is properly maintained and very well-organized. All these centers around refactoring, which reduces complexity and makes future releases more efficient. For Terraform, &lt;strong&gt;Modules helps a lot with Refactoring of your code.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modules are containers for multiple resources that are used together.&lt;/strong&gt; A module consists of a collection of &lt;code&gt;.tf&lt;/code&gt; and/or &lt;code&gt;.tf.json&lt;/code&gt; files kept together in a directory. To package and reuse resource configuration in Terraform, you'd need to understand modules and how they work, as this is the major way. &lt;strong&gt;The Agenda of this article is to:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Know what modules are&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Know how modules interact&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Know modules best practices&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;Knowledge of Terraform is needed to fully understand the contents of this article, It is assumed that you already have this Knowledge going forward.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While some who are new to terraform sometimes say Modules is a complex topic and try to avoid it, having a good understanding of it is crucial to writing codes that can be shared, easily read and reusable. Who wouldn't want that? Well, I'd say someone who don't understand how it works for sure. Let's take a brief look at what Modules really are, this insight would help going further down the somewhat intricate path of Terraform Modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Modules
&lt;/h2&gt;

&lt;p&gt;Even as a beginner to Terraform, you’ve already interacted with modules. That’s the Root module, which contains all resource configuration files ending with the &lt;code&gt;.tf&lt;/code&gt; terraform extension in the main working directory. Modules is just simply a better way of organizing and maintaining your resources configuration for easy modifications and efficient management of your infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  For Example...
&lt;/h3&gt;

&lt;p&gt;Imagine your Infrastructure code base needs several Instance resource with it's own VPC and Subnet, you can create a module with the required resource, and call it whenever you need to create such an Instance on your infrastructure. Say you need multiple of such instance, all you have to do is pass in the &lt;code&gt;count&lt;/code&gt;, or &lt;code&gt;for each&lt;/code&gt; meta-arguments when calling the module. Talking about Modules, there’s the Root module which we define. There’s also the child module, this is a module that is been called by the root module.&lt;/p&gt;

&lt;p&gt;The Instance Module in the example above is an example of a child module as we would call it from the root module. Child modules can be called multiple times within the same configuration, and multiple configurations can use the same child module, either within the same configuration or in separate configurations, allowing resource configurations to be packaged and re-used. Later on in the article, we’d see how to create a module, that would also show how we call a module to include their resources into the configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  There's some more..
&lt;/h3&gt;

&lt;p&gt;Other than the Root module and child module, there is also the Published module. Like we had the concept of backend in terraform where we can store our state locally or remotely, this is somewhat similar. Terraform has a registry where you can publish modules for others to use, and to use modules that have been published by others. This registry can either be public or private. There are lots of modules available for use today on the registry. Terraform Cloud and Terraform Enterprise both include a private module registry for sharing modules internally within your organization. Depends on what you plan to use, there’s a way to include it  or reference it in your configuration, we’d take a look at this in a later part of this article. &lt;/p&gt;

&lt;h2&gt;
  
  
  Interacting with Modules
&lt;/h2&gt;

&lt;p&gt;Now that we have a pretty detailed understanding of what modules are, let's take a look at how we can interact with it in our infrastructure configuration, i.e. calling the child module. The child module can either be sourced from&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;local path&lt;/strong&gt;, i.e. for closely related modules used primarily for the purpose of refactoring out repeated code elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Terraform module registry&lt;/strong&gt;, i.e for modules intended to be shared by multiple calling configurations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Github&lt;/strong&gt;, &lt;strong&gt;Bitbucket&lt;/strong&gt;, see more modules sources &lt;a href="https://www.terraform.io/language/modules/sources"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same source address can be specified in multiple &lt;code&gt;module&lt;/code&gt; blocks to create multiple copies of the resources defined within, possibly with different variable values. After adding, removing, or modifying &lt;code&gt;module&lt;/code&gt; blocks, you must re-run &lt;code&gt;terraform init&lt;/code&gt; to allow Terraform adjust the installed modules&lt;/p&gt;

&lt;p&gt;Our example child module block would be using a local path. To call a module means to include the contents of that module into the configuration with specific values for it's input variables. This input variables allow you tailor certain parts of Terraform modules without altering the module's own source code, therefore making your module composable and easily reusable. Take a look at this module block below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "Security" {
  source = "./modules/Security"
  vpc_id = module.VPC.vpc_id
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The label immediately after the &lt;code&gt;module&lt;/code&gt; keyword is a local name , used to refer to the instance of the module by the calling module. To be able to interact with modules you have to know the arguments for the modules. A mandatory module argument is the &lt;code&gt;source&lt;/code&gt; which tells terraform the location of the module, be it a local path or private registry or any of the source types. There is also the version argument which is recommended for modules from a registry so terraform can know which version of the module to use. As discussed already, the input variable defined by the module is also an important argument. Meta arguments are some special constructs in Terraform which are available for Resources and Modules, along with source and version. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;depends on&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;for_each&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;provider&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the example module block above, the security module source is a local path and it uses the relative filesystem path, not an absolute path. &lt;strong&gt;Terraform does not consider an absolute filesystem path(the same location in a file system relative to the root directory) to be a local path as it treats it as a remote module. It's best to use a relative filesystem path(points to a specific location in a file system relative to the current working directory you are working on).&lt;/strong&gt; The input variable there which id the vpc_id passes in a vpc_id variable from another module called VPC in the same configuration. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can use modules in various ways but it's best to keep everything easily understandable. I'd talk more about this in the next article which would be a continuation of this article and would center around "Terraform module best practices", this is in a bid to reduce the lengthiness of this article.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>terraform</category>
      <category>tutorials</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Terraform Cloud As A Remote Backend</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Tue, 05 Jul 2022 14:43:50 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/terraform-cloud-as-a-remote-backend-523e</link>
      <guid>https://community.ops.io/royalt1234/terraform-cloud-as-a-remote-backend-523e</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;On my previous &lt;a href="https://community.ops.io/royalt1234/using-aws-s3-for-terraform-backend-4ceb"&gt;article,&lt;/a&gt; I gave a step by step process on using AWS S3 for terraform backend, I also talked about terraform state file and terraform lock file quite extensively.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In summary, the state file contains information about configuration and managed infrastructure. This state is used by terraform to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructure. This state is stored by default in a local file named &lt;code&gt;terraform.tfstate&lt;/code&gt;, but it can be stored &lt;strong&gt;remotely&lt;/strong&gt;, which works better in a team environment. Read more about terraform state &lt;a href="https://www.terraform.io/language/state"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backends&lt;/strong&gt; are where Terraform's state snapshots are stored. There are different &lt;a href="https://www.terraform.io/language/settings/backends"&gt;types of backends&lt;/a&gt; on Terraform, they include; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local&lt;/strong&gt;(&lt;em&gt;which is the default&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;remote&lt;/strong&gt;(&lt;em&gt;which we would look into in this article&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3&lt;/strong&gt;(&lt;em&gt;which we've previously talked about&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes&lt;/strong&gt;(&lt;em&gt;stores the state in a Kubernetes secret&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;etcd&lt;/strong&gt;(&lt;em&gt;does not support state locking&lt;/em&gt;) and others. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Securing of your terraform state file is your responsibility.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We would be migrating a state of a project which has been local, remotely to terraform cloud. This is for better security, better team activity and a great UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to migrate our state&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Up a&lt;/strong&gt; &lt;a href="https://app.terraform.io/"&gt;&lt;strong&gt;Terraform cloud Account&lt;/strong&gt;&lt;/a&gt; - Sign up for a new account if you don't already have one &lt;a href="https://community.ops.io/images/PIhH6_UeZiM4FIY1TP29wQCO00OjFEpF9Lh7mBx0Q5s/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzNhb3Rh/NTJwdWcxNnV5eDIx/Z3djLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/PIhH6_UeZiM4FIY1TP29wQCO00OjFEpF9Lh7mBx0Q5s/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzNhb3Rh/NTJwdWcxNnV5eDIx/Z3djLnBuZw" alt="Image description" width="880" height="397"&gt;&lt;/a&gt; - Log in and create an Organization. Give it any name you like &lt;a href="https://community.ops.io/images/GQt0RBQNtbOiD0B4H5U1HS8OGVAoNjumgFn9PHDmpyg/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2RieHZs/cDF6a3JpdmV0d2Zi/bmx4LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/GQt0RBQNtbOiD0B4H5U1HS8OGVAoNjumgFn9PHDmpyg/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2RieHZs/cDF6a3JpdmV0d2Zi/bmx4LnBuZw" alt="Image description" width="880" height="553"&gt;&lt;/a&gt; - Create a &lt;code&gt;cloud&lt;/code&gt; code block on &lt;code&gt;main.tf&lt;/code&gt;. When we refactor the code, a &lt;code&gt;backend.tf&lt;/code&gt; file would be create where the &lt;code&gt;cloud&lt;/code&gt; code block would be moved to.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
cloud {
organization = "static-website"

workspaces {
  name = "static-web-dry-run"
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;strong&gt;NOTE: The organization must already exist on terraform cloud, the workspaces however doesn't have to as it would be created if it doesn't already&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authenticate with Terraform Cloud&lt;/strong&gt; - Having defined your Terraform Cloud configuration, authentication with Terraform Cloud is necessary for initialization. Run &lt;code&gt;terraform login&lt;/code&gt; &lt;a href="https://community.ops.io/images/mvM53aYbF9VMHIGGcoxeeolyZXcH1kTNTMn01mtVTYY/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3FyaTJl/bGo3M255NjBkem03/cWZ5LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/mvM53aYbF9VMHIGGcoxeeolyZXcH1kTNTMn01mtVTYY/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3FyaTJl/bGo3M255NjBkem03/cWZ5LnBuZw" alt="Image description" width="880" height="412"&gt;&lt;/a&gt; - Follow the prompt and set up the API keys which would be used for authentication &lt;a href="https://community.ops.io/images/7A_7oFf5vqaU8bNvxuVWEwg6cZFsgEupIDX1jeEnj3g/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL280OWFz/OWg4ODFob2xwd2Rp/eTNmLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/7A_7oFf5vqaU8bNvxuVWEwg6cZFsgEupIDX1jeEnj3g/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL280OWFz/OWg4ODFob2xwd2Rp/eTNmLnBuZw" alt="Image description" width="880" height="407"&gt;&lt;/a&gt; &lt;a href="https://community.ops.io/images/LUSvdX3AUOI5spimCKXlNauB0vEJ8inhdo6p8v8s-Hg/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pxcjNy/cDc3cXlyajEwOTIx/Z3Q3LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/LUSvdX3AUOI5spimCKXlNauB0vEJ8inhdo6p8v8s-Hg/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pxcjNy/cDc3cXlyajEwOTIx/Z3Q3LnBuZw" alt="Image description" width="880" height="418"&gt;&lt;/a&gt; &lt;a href="https://community.ops.io/images/dQYgyKI7ZmiGTyZTZDCebJJRXoApx9Xd_0P6fxmvQac/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2ttbGFk/ZDd1NGppcWx5NXFm/MDVpLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/dQYgyKI7ZmiGTyZTZDCebJJRXoApx9Xd_0P6fxmvQac/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2ttbGFk/ZDd1NGppcWx5NXFm/MDVpLnBuZw" alt="Image description" width="880" height="336"&gt;&lt;/a&gt; - You should get a successful output like this &lt;a href="https://community.ops.io/images/wcMslgffYioxX6emlupI06T5QR-Gf_817u8bba-x90g/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzR3ZzV2/YmNtd3JzYno2NHRv/cXk3LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/wcMslgffYioxX6emlupI06T5QR-Gf_817u8bba-x90g/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzR3ZzV2/YmNtd3JzYno2NHRv/cXk3LnBuZw" alt="Image description" width="880" height="754"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Migrate the state file&lt;/strong&gt; - Run &lt;code&gt;terraform init&lt;/code&gt; so our new &lt;code&gt;cloud&lt;/code&gt; code block configuration can be recognized &lt;a href="https://community.ops.io/images/r3k1g52yLCmKXWvwA9c9KW9DLwU1zngQF3vRpe4s_Og/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzFwaG50/c3owYWE5M3J5N2Zo/NmN6LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/r3k1g52yLCmKXWvwA9c9KW9DLwU1zngQF3vRpe4s_Og/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzFwaG50/c3owYWE5M3J5N2Zo/NmN6LnBuZw" alt="Image description" width="880" height="377"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configure the Terraform Cloud Workspace&lt;/strong&gt; - Log into the your &lt;a href="https://app.terraform.io/"&gt;Terraform cloud Account&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Confirm the workspace defined can be seen in the organization &lt;a href="https://community.ops.io/images/3BDAaiUIqGuxBePiH9ijW6cGTvvZPaTytiTfbPG1FX4/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3VtZjZm/em41eWV0ZWpoaTNk/Y2kzLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/3BDAaiUIqGuxBePiH9ijW6cGTvvZPaTytiTfbPG1FX4/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3VtZjZm/em41eWV0ZWpoaTNk/Y2kzLnBuZw" alt="Image description" width="880" height="257"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run an apply and confirm the state is there on the terraform cloud workspace &lt;a href="https://community.ops.io/images/Ev6gWb9njW_v3lMzXcImFpESvlaECPTapxd4eR12VZU/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3dzNWVj/ODVucXM3amF1cHRl/NTk4LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/Ev6gWb9njW_v3lMzXcImFpESvlaECPTapxd4eR12VZU/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3dzNWVj/ODVucXM3amF1cHRl/NTk4LnBuZw" alt="Image description" width="880" height="312"&gt;&lt;/a&gt; &lt;a href="https://community.ops.io/images/rbaNIJ54E_cAc-NwHFCTdPXOwgPT7x1AIUSKfgI30so/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2tlZmli/a2UzNnZkZ2s3eTNk/c255LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/rbaNIJ54E_cAc-NwHFCTdPXOwgPT7x1AIUSKfgI30so/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2tlZmli/a2UzNnZkZ2s3eTNk/c255LnBuZw" alt="Image description" width="880" height="556"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>tutorials</category>
    </item>
    <item>
      <title>Using AWS S3 for Terraform Backend</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Tue, 28 Jun 2022 20:44:29 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/using-aws-s3-for-terraform-backend-4ceb</link>
      <guid>https://community.ops.io/royalt1234/using-aws-s3-for-terraform-backend-4ceb</guid>
      <description>&lt;p&gt;This 3rd part of the series would be centered around migrating your &lt;a href="https://www.terraform.io/language/state"&gt;terraform state file&lt;/a&gt; which has been stored locally so far in the project, to an AWS S3 bucket so it can be accessed remotely. This is important if you intend to work in a team environment, or even for more secured storage of your state file.&lt;/p&gt;

&lt;p&gt;It is a very important file which terraform uses to manage, configure and store information about your infrastructure. Without the state, Terraform cannot function. Server-side encryption would be used to ensure that your state files are encrypted since the state files stores sensitive information like passwords. Tampering with this state file which terraform stores as 'terraform.tfstate' could be a nightmare, except you know exactly what you are doing.&lt;/p&gt;

&lt;p&gt;Terraform will lock your state for all operations that could write state. This prevents others from acquiring the lock and potentially corrupting your state. In order words, the state lock file locks the state during a deployment such that no two terraform processes try to update the same state at the same time. So in the case where you work in a dev environment and everyone have access to the code base, no two engineers can run terraform command at the same time or while a command is already running. We'd implement this using &lt;strong&gt;AWS DynamoDB&lt;/strong&gt;. State locking happens automatically on all operations that could write state. You won't see any message that it is happening. If state locking fails, Terraform will not continue.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Here is our plan to Re-initialize Terraform to use S3 backend:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;strong&gt;S3&lt;/strong&gt; and &lt;strong&gt;DynamoDB&lt;/strong&gt; resource blocks before deleting the local state file&lt;/li&gt;
&lt;li&gt;Update terraform block to introduce backend and locking&lt;/li&gt;
&lt;li&gt;Re-initialize terraform&lt;/li&gt;
&lt;li&gt;Delete the local &lt;code&gt;tfstate&lt;/code&gt; file and check the one in S3 bucket&lt;/li&gt;
&lt;li&gt;Add outputs&lt;/li&gt;
&lt;li&gt;terraform apply&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create &lt;code&gt;backend.tf&lt;/code&gt; and add the following&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "terraform_state" {
bucket = "moses-dev-terraform-bucket"
# Enable versioning so we can see the full revision history of our state files
versioning {
enabled = true
      }
# Enable server-side encryption by default
server_side_encryption_configuration {
rule {
  apply_server_side_encryption_by_default {
    sse_algorithm = "AES256"
          }
      }
   }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;strong&gt;Note: The bucket name may not work for you since buckets are unique globally in AWS, so you must give it a unique name. Read more about AWS S3 Bucket Naming Policies &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html"&gt;Here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create DynamoDB table to handle locking. With a cloud storage database like DynamoDB, anyone running Terraform against the same infrastructure can use a central location to control a situation where Terraform is running at the same time from multiple different people.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_dynamodb_table" "terraform_locks" {
name         = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key     = "LockID"
attribute {
name = "LockID"
type = "S"s
      }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;strong&gt;Terraform expects that both S3 bucket and DynamoDB resources are already created before we configure the backend. So, let us run &lt;code&gt;terraform apply&lt;/code&gt; to provision resources.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure S3 backend&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
backend "s3" {
bucket         = "moses-dev-terraform-bucket"
key            = "global/s3/terraform.tfstate"
region         = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt        = true
      }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;strong&gt;Now, Run &lt;code&gt;terraform init&lt;/code&gt; and confirm you are OK to change the backend by typing 'yes'&lt;/strong&gt; &lt;a href="https://community.ops.io/images/TETC_HalpYstZNryFfAsohdTvxhXpCbwCF2tzOQQ2Gs/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvdmgw/bXIyOXY2aXN4MGRo/YzVpenUucG5n" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/TETC_HalpYstZNryFfAsohdTvxhXpCbwCF2tzOQQ2Gs/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvdmgw/bXIyOXY2aXN4MGRo/YzVpenUucG5n" alt="Image description" width="880" height="222"&gt;&lt;/a&gt;  &lt;a href="https://community.ops.io/images/V3wOYh25HZC66hs445-002v297DcRo_B0coQHgBhtg4/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvOTZ1/bnRpYmJqdng2bHdo/ZWkycGsucG5n" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/V3wOYh25HZC66hs445-002v297DcRo_B0coQHgBhtg4/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvOTZ1/bnRpYmJqdng2bHdo/ZWkycGsucG5n" alt="Image description" width="880" height="238"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify the changes - Checking AWS, the following will be noted: &lt;strong&gt;&lt;em&gt;tfstatefile is now inside the S3 bucket&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://community.ops.io/images/olMPbEplb042wG9pWeXrihnD41pCKsDMKtjZh9M0KNM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3J0cXNx/MXpwcmI0aW1hanVj/aGVqLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/olMPbEplb042wG9pWeXrihnD41pCKsDMKtjZh9M0KNM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3J0cXNx/MXpwcmI0aW1hanVj/aGVqLnBuZw" alt="Image description" width="880" height="432"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;DynamoDB table which we create has an entry which includes state file status&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://community.ops.io/images/ZWmSwcuapO3Z6dxMuB80vNjZXFNpLnemvDhVnKfCHzM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2Z5bnk1/NTJlMHgzbjYzM3Y2/ams2LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/ZWmSwcuapO3Z6dxMuB80vNjZXFNpLnemvDhVnKfCHzM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2Z5bnk1/NTJlMHgzbjYzM3Y2/ams2LnBuZw" alt="Image description" width="880" height="430"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add Terraform Output&lt;br&gt;
&lt;strong&gt;Add the following to &lt;code&gt;output.tf&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "s3_bucket_arn" {
value       = aws_s3_bucket.terraform_state.arn
description = "The ARN of the S3 bucket"
    }
output "dynamodb_table_name" {
value       = aws_dynamodb_table.terraform_locks.name
description = "The name of the DynamoDB table"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;terraform apply&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Terraform will automatically read the latest state from the S3 bucket to determine the current state of the infrastructure. Even if another engineer has applied changes, the state file will always be up to date. Check the tfstate file in S3 and click the version tab to see the different versions of the tfstate file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;In the next part of the series, Modules would be discussed, and more some more refactoring as well.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Code from &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>devops</category>
      <category>tutorials</category>
    </item>
    <item>
      <title>CREATING A COMPANY INFRASTRUCTURE IN AWS USING TERRAFORM - Part 2</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Tue, 28 Jun 2022 16:29:44 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/creating-a-company-infrastructure-in-aws-using-terraform-part-2-2mp2</link>
      <guid>https://community.ops.io/royalt1234/creating-a-company-infrastructure-in-aws-using-terraform-part-2-2mp2</guid>
      <description>&lt;p&gt;This article is part 2 of a series of articles focused on building a company's infrastructure on AWS using Terraform. You can read up &lt;a href="https://community.ops.io/royalt1234/creating-a-company-infrastructure-in-aws-using-terraform-5hd7"&gt;Part 1&lt;/a&gt; where we introduced the topic, basic setup, wrote terraform code which creates our VPC and public subnets. By the end of this article, we would understand and write codes that would create the following resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Private Subnets&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;Internet Gateway and NAT Gateway&lt;/li&gt;
&lt;li&gt;EIP and Routes Tables&lt;/li&gt;
&lt;li&gt;Security groups&lt;/li&gt;
&lt;li&gt;Certificate from amazon certificate manager&lt;/li&gt;
&lt;li&gt;Autoscaling groups&lt;/li&gt;
&lt;li&gt;Storage and database&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Code from &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Networking
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Private subnets &amp;amp; best practices
&lt;/h4&gt;

&lt;p&gt;Create 4 private subnets, keep in mind following principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you use variables or length() function to determine the number of AZs&lt;/li&gt;
&lt;li&gt;Use variables and cidrsubnet() function to allocate vpc_cidr for subnets&lt;/li&gt;
&lt;li&gt;Keep variables and resources in separate files for better code structure and readability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;main.tf&lt;/code&gt; private subnets code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create private subnets
resource "aws_subnet" "private" {
  count = var.preferred_number_of_public_subnets == null ? length(data.aws_availability_zones.available.names) : var.preferred_number_of_public_subnets 
  vpc_id                     = aws_vpc.main.id
  &amp;lt;!-- cidr_block                 = cidrsubnet(var.vpc_cidr, 4 , count.index) --&amp;gt;
  cidr_block                 = var.public_subnets[count.index]
  map_public_ip_on_launch    = true
  availability_zone          = data.aws_availability_zones.available.names[count.index]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;variables.tf&lt;/code&gt; private subnets variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "preferred_number_of_private_subnets" {
  default = null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt; private subnets variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;preferred_number_of_private_subnets = 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Tag all the resources you have created so far. Explore how to use format() and count functions to automatically tag subnets with its respective number.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TAGS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;terraform.tfvars&lt;/code&gt; file, add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tags = {
  Enviroment = "production"
  Owner-Email = "owner@mail.com"
  Managed-By = "Terraform"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;variables.tf&lt;/code&gt; file, add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "tags" {
  description = "A mapping of tags to assign to all resources."
  type        = map(string)
  default     = {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now we can tag our resources with the tags we have defined in the &lt;code&gt;variables.tf&lt;/code&gt; file like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tags = merge(
    var.tags,
    {
      Name = "Name of the resource"
    },
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits of tagging with this approach: we only need to change the tags in one place (&lt;code&gt;terraform.tfvars&lt;/code&gt;) and we can easily see what resources are tagged with what tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internet Gateways &amp;amp; format() function
&lt;/h2&gt;

&lt;p&gt;Create an Internet Gateway in a separate Terraform file &lt;code&gt;internet_gateway.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_internet_gateway" "ig" {
  vpc_id = aws_vpc.main.id

  tags = merge(
    var.tags,
    {
      Name = format("%s-%s!", aws_vpc.main.id,"IG")
    } 
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used &lt;code&gt;format&lt;/code&gt; to dynamically generate the name of the resource by using &lt;strong&gt;&lt;em&gt;&lt;code&gt;format()&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The first part of the &lt;code&gt;%s&lt;/code&gt; takes the interpolated value of &lt;code&gt;aws_vpc.main.id&lt;/code&gt; while the second &lt;code&gt;%s&lt;/code&gt;appends a literal string IG and finally an exclamation mark is added in the end.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NAT Gateways
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create 1 NAT Gateways and 1 Elastic IP (EIP) addresses
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;create a new file called &lt;code&gt;natgateway.tf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; We need to create an Elastic IP for the NAT Gateway, and you can see the use of &lt;code&gt;depends_on&lt;/code&gt; to indicate that the Internet Gateway resource must be available before this should be created. Although Terraform does a good job to manage dependencies, but in some cases, it is good to be explicit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_eip" "nat_eip" {
  vpc        = true
  depends_on = [aws_internet_gateway.ig]

  tags = merge(
    var.tags,
    {
      Name = format("%s-EIP", var.name)
    },
  )
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = element(aws_subnet.public.*.id, 0)
  depends_on    = [aws_internet_gateway.ig]

  tags = merge(
    var.tags,
    {
      Name = format("%s-Nat", var.name)
    },
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used the &lt;strong&gt;&lt;em&gt;&lt;code&gt;element()&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; function to select the first element of the array of subnets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element(list, index)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element(aws_subnet.public.*.id, 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 Fetches the first element of the array of subnets.&lt;/p&gt;
&lt;h3&gt;
  
  
  AWS ROUTES
&lt;/h3&gt;

&lt;p&gt;Create a file called &lt;code&gt;route_tables.tf&lt;/code&gt; and use it to create routes for both public and private subnets.&lt;/p&gt;

&lt;p&gt;Now we Create a route table for the public subnets and a route table for the private subnets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aws_route_table&lt;/li&gt;
&lt;li&gt;aws_route&lt;/li&gt;
&lt;li&gt;aws_route_table_association
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create private route table
resource "aws_route_table" "private-rtb" {
  vpc_id = aws_vpc.main.id

  tags = merge(
    var.tags,
    {
      Name = format("%s-Private-Route-Table", var.name)
    },
  )
}

# associate all private subnets to the private route table
resource "aws_route_table_association" "private-subnets-assoc" {
  count          = length(aws_subnet.private[*].id)
  subnet_id      = element(aws_subnet.private[*].id, count.index)
  route_table_id = aws_route_table.private-rtb.id
}

# create route table for the public subnets
resource "aws_route_table" "public-rtb" {
  vpc_id = aws_vpc.main.id

  tags = merge(
    var.tags,
    {
      Name = format("%s-Public-Route-Table", var.name)
    },
  )
}

# create route for the public route table and attach the internet gateway
resource "aws_route" "public-rtb-route" {
  route_table_id         = aws_route_table.public-rtb.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.ig.id
}

# associate all public subnets to the public route table
resource "aws_route_table_association" "public-subnets-assoc" {
  count          = length(aws_subnet.public[*].id)
  subnet_id      = element(aws_subnet.public[*].id, count.index)
  route_table_id = aws_route_table.public-rtb.id
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  AWS Identity and Access Management
&lt;/h3&gt;
&lt;h4&gt;
  
  
  IAM and Roles
&lt;/h4&gt;

&lt;p&gt;We want to pass an IAM role our EC2 instances to give them access to some specific resources, so we need to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create AssumeRole&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assume Role uses Security Token Service (STS) API that returns a set of temporary security credentials that you can use to access AWS resources that you might not normally have access to. These temporary credentials consist of an access key ID, a secret access key, and a security token. Typically, you use AssumeRole within your account or for cross-account access.&lt;/p&gt;

&lt;p&gt;Add the following code to a new file named &lt;code&gt;roles.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "ec2_instance_role" {
name = "ec2_instance_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      },
    ]
  })

  tags = merge(
    var.tags,
    {
      Name = "aws assume role"
    },
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are creating AssumeRole with AssumeRole policy. It grants to an entity, in our case it is an EC2, permissions to assume the role.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create IAM policy for this role
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_policy" "policy" {
  name        = "ec2_instance_policy"
  description = "A test policy"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ec2:Describe*",
        ]
        Effect   = "Allow"
        Resource = "*"
      },
    ]

  })

  tags = merge(
    var.tags,
    {
      Name =  "aws assume policy"
    },
  )

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Attach the Policy to the IAM Role&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we will be attaching the policy which we created above, to the role we created in the first step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role_policy_attachment" "test-attach" {
    role       = aws_iam_role.ec2_instance_role.name
    policy_arn = aws_iam_policy.policy.arn
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create an Instance Profile and interpolate the IAM Role
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_instance_profile" "ip" {
    name = "aws_instance_profile_test"
    role =  aws_iam_role.ec2_instance_role.name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CREATE SECURITY GROUPS
&lt;/h2&gt;

&lt;p&gt;We are going to create all the security groups in a single file, then we are going to reference this security group within each resources that needs it. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;I've taken a codesnap of the block of code for this resource as it's quite lengthy, this would be done for any lenghty code for the remainder of this series. I would leave a link to my repo at the end of this article should you need to look through.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Create a file called &lt;code&gt;security.tf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the following &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/security.tf"&gt;code&lt;/a&gt; to the file.
&lt;img src="https://community.ops.io/images/ZVV85sYZ6kuFDPSbVZ5jijtVhRKZVJvHDOo-JNVhDxY/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvem1u/aHp0czE3OW82Mjc3/OHhncWYucG5n" alt="Image description" width="880" height="1546"&gt; &lt;img src="https://community.ops.io/images/qgXe-lhIec76uK50VlC8iHfO0Yk_CD4Q3Yq4xhE5ttU/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvZ3Y1/N21zMmU1OWtmdXU2/dXlqZmUucG5n" alt="Image description" width="880" height="1200"&gt; &lt;img src="https://community.ops.io/images/9kAhvyRU56ExEZLj-00-k66aGO9ozfIEEaS5_EH-ee4/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvY2Ft/cjlvaWdkaDExYW5z/d3RneXEucG5n" alt="Image description" width="880" height="1512"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;We used the &lt;code&gt;aws_security_group_rule&lt;/code&gt; to reference another security group in a security group.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CREATE CERTIFICATE FROM AMAZON CERIFICATE MANAGER
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/cert.tf"&gt;&lt;code&gt;cert.tf&lt;/code&gt;&lt;/a&gt; file 
&lt;img src="https://community.ops.io/images/jj1g2WPjJNWAY-YXLElB02LcJ4T9eCKaPtCJuO1LqOA/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2FyNGow/aXl6NGZ1ZXZobnI5/bmltLnBuZw" alt="Image description" width="880" height="1288"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create an external (Internet facing) Application Load Balancer (ALB)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a file called &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/alb.tf"&gt;&lt;code&gt;alb.tf&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First of all we will create the ALB, then we create the target group and lastly we will create the listener rule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/qBgO4o9HykB_mJYLjmnuR3wMe3ZHa-MQoGS4N_KBcPM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21vdWg2/Nm4yc3ozbTR6OGdq/NHgwLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/qBgO4o9HykB_mJYLjmnuR3wMe3ZHa-MQoGS4N_KBcPM/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21vdWg2/Nm4yc3ozbTR6OGdq/NHgwLnBuZw" alt="Image description" width="880" height="1114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Internal (Internal) Application Load Balancer (ALB)
&lt;/h2&gt;

&lt;p&gt;This follows the same set up as external ALB&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the following Code to &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/alb.tf"&gt;&lt;code&gt;alb.tf&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/e_r870eG0dL6Ieig6Xgpbp_P4-bybUO-NoWGsPgG3ag/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2p5aHRv/aXJiNzY3cm41bGs3/ZDRsLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/e_r870eG0dL6Ieig6Xgpbp_P4-bybUO-NoWGsPgG3ag/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2p5aHRv/aXJiNzY3cm41bGs3/ZDRsLnBuZw" alt="Image description" width="880" height="2245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CREATING AUSTOALING GROUPS
&lt;/h2&gt;

&lt;p&gt;We need to configure our ASG to be able to scale the EC2s out and in depending on the application traffic.&lt;/p&gt;

&lt;p&gt;we need to create the launch template and the the AMI before creating the ASG. For now we will use a random AMI from AWS.&lt;/p&gt;

&lt;p&gt;Based on our Architetecture we need for Auto Scaling Groups for bastion, nginx, wordpress and tooling, so we will create two files; &lt;code&gt;asg-bastion-nginx.tf&lt;/code&gt; will contain Launch Template and Autoscaling group for Bastion and Nginx, then asg-wordpress-tooling.tf will contain Launch Template and Autoscaling group for wordpress and tooling&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/asg-bastion-nginx.tf"&gt;&lt;code&gt;asg-bastion-nginx.tf&lt;/code&gt;&lt;/a&gt; and add the following&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/Flm6g3BHkm2YMk71NdKA1Q60KqWtOIMgHFEkS3V__DI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzJqM2lw/YzZqeDJldG5mMDJl/ODU1LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/Flm6g3BHkm2YMk71NdKA1Q60KqWtOIMgHFEkS3V__DI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzJqM2lw/YzZqeDJldG5mMDJl/ODU1LnBuZw" alt="Image description" width="880" height="2495"&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://community.ops.io/images/FBsC6U1XpjrF-i08aZd4WgIvozIMms4GaGzbCxrAPW0/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2Vrd254/MnNrdmlsZDJhdWli/NGE5LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/FBsC6U1XpjrF-i08aZd4WgIvozIMms4GaGzbCxrAPW0/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2Vrd254/MnNrdmlsZDJhdWli/NGE5LnBuZw" alt="Image description" width="880" height="1953"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/asg-wordpress-tooling.tf"&gt;&lt;code&gt;asg-wordpress-tooling.tf&lt;/code&gt;&lt;/a&gt; and paste the following code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/pDuQyhxeNhtMrlZXJ9knfn84AAmNQRjBjZWyVptso0Q/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzF5YWgz/cjdjeGJmMWkzZjQ3/bXVrLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/pDuQyhxeNhtMrlZXJ9knfn84AAmNQRjBjZWyVptso0Q/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzF5YWgz/cjdjeGJmMWkzZjQ3/bXVrLnBuZw" alt="Image description" width="880" height="1618"&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://community.ops.io/images/lmAj2kkMtpY5D5kDih3yAhNM7Yp_HfBRrmbMVMnDUdk/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3gzM2Ft/YW94b2g1cnp4a3F0/NGN6LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/lmAj2kkMtpY5D5kDih3yAhNM7Yp_HfBRrmbMVMnDUdk/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3gzM2Ft/YW94b2g1cnp4a3F0/NGN6LnBuZw" alt="Image description" width="880" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  STORAGE AND DATABASE
&lt;/h3&gt;

&lt;p&gt;We will be creating RDS, EFS and KMS for the resources. Here&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Elastic File System (EFS).&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;efs.tf&lt;/code&gt; file: In order to create an EFS you need to create a KMS key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following code to &lt;code&gt;efs.tf&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/HriEuPCu_NKpVCLbhwdsQw91BdP63Ax0RQd3KpENw1A/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2hmZXdv/dnIxamw3MzU4bWcy/bmU2LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/HriEuPCu_NKpVCLbhwdsQw91BdP63Ax0RQd3KpENw1A/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2hmZXdv/dnIxamw3MzU4bWcy/bmU2LnBuZw" alt="Image description" width="880" height="2337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create RDS instance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/blob/master/terraform/rds.tf"&gt;&lt;code&gt;rds.tf&lt;/code&gt;&lt;/a&gt; file and add the following code to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/CEwWR-qJD1RapHHYBipheyFsDiFTyceTvBi-TK9WU_Y/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2tuN2g5/NjdoODNzM2JhZ3Rh/NnJkLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/CEwWR-qJD1RapHHYBipheyFsDiFTyceTvBi-TK9WU_Y/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2tuN2g5/NjdoODNzM2JhZ3Rh/NnJkLnBuZw" alt="Image description" width="880" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update &lt;code&gt;variable.tf&lt;/code&gt; to include the variables we've used so far. The file should look like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/mqGBi_krbLN0LaZEbYrIGJM6Yt43ePYKQUolNchxUkc/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2V6cTNt/NG1iMXowN3NzbHZm/b2xsLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/mqGBi_krbLN0LaZEbYrIGJM6Yt43ePYKQUolNchxUkc/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2V6cTNt/NG1iMXowN3NzbHZm/b2xsLnBuZw" alt="Image description" width="880" height="2054"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update &lt;code&gt;terraform.tfvars&lt;/code&gt; to include the variables we've used so far. The file should look like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;region = "us-east-1"

vpc_cidr = "172.16.0.0/16"

enable_dns_support = "true"

enable_dns_hostnames = "true"

enable_classiclink = "false"

enable_classiclink_dns_support = "false"

preferred_number_of_public_subnets = 2

preferred_number_of_private_subnets = 4

environment = "production"

ami = "ami-0b0af3577fe5e3532"

keypair = "terraform"

# Ensure to change this to your acccount number
account_no = "012345678901 "
tags = {
  Enviroment      = "production"
  Owner-Email     = "name@mail.com"
  Managed-By      = "Terraform"
  Billing-Account = "1234567890"
}

master-password = "admin12345"

master-username = "admin12345"

db_name = "Doeita-db"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Pheew! That was some long lines of codes and less story, I know I know! Well, our infrastructure is quite a complex one, so it should be expected. The code we've written so far is pretty much a large percentage of the entire code needed. Moving on, we would be introducing backend storage of our terraform state file on amazon s3 and introducing modules for refactoring and better structure of our codes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Code From &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/royalt1234/terrafrom-prj17-code/tree/master/terraform"&gt;&lt;strong&gt;&lt;em&gt;HERE IS A LINK TO MY GITHUB REPO FOR THIS PROJECT&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
      <category>iac</category>
    </item>
    <item>
      <title>Running Docker Without Sudo - EC2 server</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Sun, 26 Jun 2022 09:33:09 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/running-docker-without-sudo-ec2-server-l7h</link>
      <guid>https://community.ops.io/royalt1234/running-docker-without-sudo-ec2-server-l7h</guid>
      <description>&lt;p&gt;I was quite comfortable running my docker using &lt;code&gt;sudo&lt;/code&gt;, not that I preferred it but I really had no option until I had to run a CI/CD pipeline which throws error as a result of running the commands with &lt;code&gt;sudo&lt;/code&gt;. By default, the docker command can only be run by the root user or by a user in the docker group, which is automatically created during Docker’s installation process. If you attempt to run the docker command without prefixing it with &lt;code&gt;sudo&lt;/code&gt; or without being in the docker group, you’ll get an output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made me further troubleshoot to get a solution, this article is about my little experience resolving the issue, most especially if you experience this issue running docker on a server. &lt;/p&gt;

&lt;p&gt;I ran my docker on an EC2 instance, even after following the commands necessary for me to run docker without using &lt;code&gt;sudo&lt;/code&gt;. It turns out I had to reboot my server, and not just exit the terminal and ssh back in to the terminal as a lot of articles I came across advised. Well, that may have worked for others, but it did not for me. If it's on a local terminal, after following the process, you can close your terminal and come back in. The changes would be effected, but it's not so for servers, you have to reboot the server.&lt;/p&gt;

&lt;p&gt;Also, I'd like to add that it is important you run docker without &lt;code&gt;sudo&lt;/code&gt; especially in a Jenkins Job as it would throw errors as seen below. &lt;br&gt;
&lt;a href="https://community.ops.io/images/PSs9aCTHXl0j-GxT1EXKlkUCKih0_JlPZUZ187H8LTI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pqMjJs/bnZ2ZTF5bWlqcDJt/emY1LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/PSs9aCTHXl0j-GxT1EXKlkUCKih0_JlPZUZ187H8LTI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pqMjJs/bnZ2ZTF5bWlqcDJt/emY1LnBuZw" alt="docker-jenkins-1" width="880" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to avoid typing &lt;code&gt;sudo&lt;/code&gt; whenever you run the docker command, add your username to the docker group. That being said, the following are steps to run Docker without &lt;code&gt;sudo&lt;/code&gt;(I'd still like to emphasize, for EC2 servers or any other cloud provider servers,):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add your username to the docker group:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo usermod -aG docker ${USER}
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply the new group membership. In my own case, I had to reboot my ec2 server for it to take effect, my server user had no password. If your user has a password, then run &lt;code&gt;su - ${USER}&lt;/code&gt;. You'd be prompted to enter your password, do that and the changes would take effect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirm that your user is now added to the docker group by running the command &lt;code&gt;groups&lt;/code&gt;. You should now see your user amongts the group. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's all, you can now go ahead and run docker without &lt;code&gt;sudo&lt;/code&gt;. This worked for me and my Jenkins job which failed worked right after the above steps &lt;br&gt;
&lt;a href="https://community.ops.io/images/0KKKuWwGnnaRZMXkMVIIo8xPky16yRN1Tg5-hvh6L6w/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2o2emZ3/NG8ydXQ1NG5mc3F2/YjJ0LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/0KKKuWwGnnaRZMXkMVIIo8xPky16yRN1Tg5-hvh6L6w/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2o2emZ3/NG8ydXQ1NG5mc3F2/YjJ0LnBuZw" alt="docker-jenkins" width="880" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>jenkins</category>
      <category>aws</category>
    </item>
    <item>
      <title>Kubernetes Cluster on aws EKS using Terraform</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Sun, 26 Jun 2022 08:34:40 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/kubernetes-cluster-on-aws-eks-using-terraform-aa2</link>
      <guid>https://community.ops.io/royalt1234/kubernetes-cluster-on-aws-eks-using-terraform-aa2</guid>
      <description>&lt;p&gt;Quite recently, I was tasked with creating a production ready Kubernetes cluster from the ground up at &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt; where I Learn DevOps via a Project Based Learning model. This task gave me a deep and practical insight into the technical structure and setup of Kubernetes. Though it took me a while, I was able to set it up as requested and as per documentation. &lt;/p&gt;

&lt;p&gt;Moving forward with the knowledge gained, I decided to set up an AWS EKS Cluster which I would use for some application deployments. This next tasks would center around deployments and persisting data in k8s. However, this article is only a guide to provisioning your own &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/clusters.html"&gt;AWS EKS Cluster&lt;/a&gt; using IaC(Terraform). It is advisable to do this first with the console if you don't already have knowledge as to how it all works. &lt;/p&gt;

&lt;p&gt;Terraform is the IaC tool for this guide(knowledge of terraform is a prerequisite for this process), below are the steps to follow in setting up your EKS Cluster using terraform on your control machine;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup a controller client machine(can be an EC2 instance or your local machine)&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://www.terraform.io/downloads"&gt;Terraform&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/"&gt;Kubectl&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;AWSCLI&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/install-aws-iam-authenticator.html"&gt;aws-iam-authenticator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a folder where you'd clone the Terraform repo already provide by Hashicorp/AWS &lt;a href="https://community.ops.io/images/V73g5ykT8ciqcierVgBGLvJ0cYrtApBbsON32fbEtgo/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2t1Zjll/YTY0OHZndDkwemk3/ZGhvLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/V73g5ykT8ciqcierVgBGLvJ0cYrtApBbsON32fbEtgo/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2t1Zjll/YTY0OHZndDkwemk3/ZGhvLnBuZw" alt="repo" width="880" height="563"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clone down the &lt;a href="https://github.com/hashicorp/terraform-provider-aws"&gt;Github Repo&lt;/a&gt; into your controller client machine &lt;a href="https://community.ops.io/images/2cHVeuOx_rnCWF1HCZ1Q2o8b3wPpeSfvdxggsc0e6oI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzFjYXp6/ZjM0dW13NGh5czR5/YXpoLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/2cHVeuOx_rnCWF1HCZ1Q2o8b3wPpeSfvdxggsc0e6oI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzFjYXp6/ZjM0dW13NGh5czR5/YXpoLnBuZw" alt="repo clone" width="880" height="194"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into the folder, &lt;code&gt;cd&lt;/code&gt; into examples dir, &lt;code&gt;cd&lt;/code&gt; into eks-getting-started &lt;a href="https://community.ops.io/images/XUq59HqSDez7Ej-T3lJqFj7cZld5eHOfvV7YGzoNWQo/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2JyOWNs/Yjl1azAzY20zeGcx/aTJiLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/XUq59HqSDez7Ej-T3lJqFj7cZld5eHOfvV7YGzoNWQo/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2JyOWNs/Yjl1azAzY20zeGcx/aTJiLnBuZw" alt="Image" width="880" height="522"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ls&lt;/code&gt; to see the '.tf' files &lt;a href="https://community.ops.io/images/XEMRrnNmLJ6bpMz41PZzBBsjEd4Ox-NAXIqRfJ58_oU/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzU3b3p2/MWdvd3lkbXc1bDV5/d3BxLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/XEMRrnNmLJ6bpMz41PZzBBsjEd4Ox-NAXIqRfJ58_oU/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzU3b3p2/MWdvd3lkbXc1bDV5/d3BxLnBuZw" alt="tf files" width="880" height="226"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feel free editing to your preference, things such as Region, names, instance type for the worker nodes, version of Kubernetes among others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;terraform init&lt;/code&gt; to initialize the folder, &lt;code&gt;terraform plan&lt;/code&gt; to see what resources would be created. 18 resources would be created in building this cluster. &lt;code&gt;terraform apply&lt;/code&gt; to create the resources. It would take some 8-10 min for the cluster to be built and ready to go. &lt;a href="https://community.ops.io/images/GZBizTvhj7IPeKv6YMYdkCdnIVWwOV2X9zHehy9Pi3I/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2x1bHln/ZzFvcWdtOXU1ZTJh/ZHliLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/GZBizTvhj7IPeKv6YMYdkCdnIVWwOV2X9zHehy9Pi3I/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL2x1bHln/ZzFvcWdtOXU1ZTJh/ZHliLnBuZw" alt="Init" width="880" height="587"&gt;&lt;/a&gt; &lt;a href="https://community.ops.io/images/uDFa-5wY24vWCQooKJV6p9-EX5ibXTxWhrONczpbI4o/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21lMTA5/eHMxOTE4c3Fmd25s/cWdzLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/uDFa-5wY24vWCQooKJV6p9-EX5ibXTxWhrONczpbI4o/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21lMTA5/eHMxOTE4c3Fmd25s/cWdzLnBuZw" alt="apply" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now the cluster is built, you have to update the --kubeconfig with the awscli command&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws eks --region &amp;lt;region&amp;gt; update-kubeconfig --name &amp;lt;cluster-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;a href="https://community.ops.io/images/YnACpiFVs_93WIoH9m6aoxiq_vnvLL45qvZGpdP73-E/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzZnZ3Rn/ZDhndmt1cjliamRn/a3hnLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/YnACpiFVs_93WIoH9m6aoxiq_vnvLL45qvZGpdP73-E/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzZnZ3Rn/ZDhndmt1cjliamRn/a3hnLnBuZw" alt="kubeconfig" width="880" height="90"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test that everything works by running a &lt;code&gt;kubectl&lt;/code&gt; command(any kubectl command) to show the nodes in your cluster&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get nodes -o wide
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;a href="https://community.ops.io/images/AVjwsolyRDJOO2plmljPwByK9waLjgkM0I1qzG1ee2M/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3p5aTNv/M2JldXRobWlzOTd3/Nm5zLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/AVjwsolyRDJOO2plmljPwByK9waLjgkM0I1qzG1ee2M/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3p5aTNv/M2JldXRobWlzOTd3/Nm5zLnBuZw" alt="get-nodes" width="880" height="102"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>aws</category>
      <category>iac</category>
    </item>
    <item>
      <title>CREATING A COMPANY INFRASTRUCTURE IN AWS USING TERRAFORM - Part 1</title>
      <dc:creator>Moses Itoya</dc:creator>
      <pubDate>Wed, 01 Jun 2022 14:07:54 +0000</pubDate>
      <link>https://community.ops.io/royalt1234/creating-a-company-infrastructure-in-aws-using-terraform-5hd7</link>
      <guid>https://community.ops.io/royalt1234/creating-a-company-infrastructure-in-aws-using-terraform-5hd7</guid>
      <description>&lt;p&gt;This article is part of a series of articles focused on building a company's infrastructure on AWS using Terraform, all of which(and more) I learnt on the &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt; platform. The Darey.io platform adopts a project based learning style which has proven very effective in development, growth and career success evident in a lot of DevOps Engineers who have passed through the DevOps program on the platform. &lt;/p&gt;

&lt;p&gt;The said company we would create an infrastructure for on this series needs a WordPress solution for its developers and a tooling solution for it's DevOps engineers. This would all be in a private network. Part 1 centers on basic intro, VPC and subnets creation. I'd be taking you through the processes involved, should you want to create same or similar infrastructure, while also learning and improving on terraform. You would write the code with Terraform and build the infrastructure as seen below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/gwSds1P18RSJJB0RBFmnagDVJWnbmzRKeBmFDF75KlI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzB2YTA3/YjU3NDh3dXpnNTA4/YXBuLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/gwSds1P18RSJJB0RBFmnagDVJWnbmzRKeBmFDF75KlI/w:880/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzLzB2YTA3/YjU3NDh3dXpnNTA4/YXBuLnBuZw" alt="aws-infra" width="843" height="894"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Image from &lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Programmable infrastructures allow you to manage on-premises and cloud resources through code instead of with the management platforms and manual methods traditionally used by IT teams.&lt;br&gt;
An infrastructure captured in code is simpler to manage, can be replicated or altered with greater accuracy, and benefits from all sorts of automation. It can also have changes to it implemented and tracked with the version control methods customarily used in software development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 1 - Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;AWS strongly recommends following the security practice of granting least privilege, i.e. the minimum set of permissions necessary to perform a given task. So its best to look at the infrastructure and see what services would be created or accessed and the required permissions. However, you would create a user with programmatic access and AdministratorAccess permissions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure programmatic access from your work station. I would recommend using the AWSCLI for this with the &lt;code&gt;aws configure&lt;/code&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a S3 bucket via the console to store Terraform state file. View the newly created S3 bucket via your terminal to confirm the access was configured properly. You are all set up when you can see it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best practices are to ensure every resource is tagged, using multiple key-value pairs. Secondly, write reusable code. We should avoid hard coding values wherever possible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;STEP 2 - VPC Creation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Create a Directory Structure which should have:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;folder(name it whatever you like)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;main.tf&lt;/code&gt; file which is our main configuration file where we are going to define our resource definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;variables.tf&lt;/code&gt; file which would store your variable declarations. It's best to use variables as it keeps your code neat and tidy. Variables prevents hard coding values and makes code easily reusable. &lt;a href="https://community.ops.io/images/_X8rIO8Zk_a4f7kqHwKj1Ys76XvCypPkFU-5S6yG-mI/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMveWtp/eHd0ZHJ3Y3l5cjlx/ZDBid24ucG5n" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/_X8rIO8Zk_a4f7kqHwKj1Ys76XvCypPkFU-5S6yG-mI/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMveWtp/eHd0ZHJ3Y3l5cjlx/ZDBid24ucG5n" alt="variables.tf" width="880" height="1090"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt; file which would contain the values for your variables. This project would get complex really soon and I think it's best to understand variables and how manage them effectively. I came across this great &lt;a href="https://spacelift.io/blog/terraform-tfvars"&gt;article&lt;/a&gt; from Spacelift that did justice to that. &lt;a href="https://community.ops.io/images/qQCBaU11A5spvkl-5fdivW1u_D1vtD3Xf4u8jue8Rm0/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvM3Ru/eHI4aTMwdGU1ZnZy/MnJkcTUucG5n" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/qQCBaU11A5spvkl-5fdivW1u_D1vtD3Xf4u8jue8Rm0/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvM3Ru/eHI4aTMwdGU1ZnZy/MnJkcTUucG5n" alt="terraform.tfvars" width="880" height="749"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.&lt;br&gt;
Set up your Terraform CLI&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
Add a provider block(AWS is the provider)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = var.region
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.&lt;br&gt;
Add a resource that would create a VPC for the infra.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create VPC
resource "aws_vpc" "main" {
  cidr_block                     = var.vpc_cidr
  enable_dns_support             = var.enable_dns_support 
  enable_dns_hostnames           = var.enable_dns_support
  enable_classiclink             = var.enable_classiclink
  enable_classiclink_dns_support = var.enable_classiclink
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.&lt;br&gt;
Run &lt;code&gt;terraform init&lt;/code&gt;. Terraform relies on plugins called “providers” to interact with cloud providers, SaaS providers, and other APIs. Terraform configurations must declare which providers they require so that Terraform can install and use them. &lt;code&gt;terraform init&lt;/code&gt; finds and downloads those providers from either the public Terraform Registry or a third-party provider registry. This is the part that generates the &lt;code&gt;.terraform.lock.hcl&lt;/code&gt; you would notice when you run &lt;code&gt;terraform init&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Notice that a new directory has been created:  &lt;code&gt;.terraform\....&lt;/code&gt; This is where Terraform keeps plugins. Generally, it is safe to delete this folder. It just means that you must execute terraform init again, to download them.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;6.&lt;br&gt;
Run &lt;code&gt;terraform plan&lt;/code&gt; to see what would be created when you decide to create your &lt;code&gt;aws_vpc&lt;/code&gt; resource.&lt;/p&gt;

&lt;p&gt;7.&lt;br&gt;
Run &lt;code&gt;terraform apply&lt;/code&gt; if only you accept the changes that would occur.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A new file is created &lt;code&gt;terraform.tfstate&lt;/code&gt; This is how Terraform keeps itself up to date with the exact state of the infrastructure. It reads this file to know what already exists, what should be added, or destroyed based on the entire terraform code that is being developed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also created is the lock file &lt;code&gt;.terraform.lock.hcl&lt;/code&gt; which contains information about the providers; in future command runs, Terraform will refer to that file in order to use the same provider versions as it did when the file was generated.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;STEP 3 - Subnet Creation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;According to the infrastructure design, you will require 6 subnets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 public&lt;/li&gt;
&lt;li&gt;2 private for webservers&lt;/li&gt;
&lt;li&gt;2 private for data layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create the first 2 public subnets.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do not try to memorize the code for anything on terraform. Just understand the structure. You can easily get whatever resource block, from any provider you need on &lt;a href="https://registry.terraform.io/."&gt;terraform registry&lt;/a&gt; All you have to do is to tweak it to your desired resource for your infra. Reason a good understanding of the structure of terraform is key. With time, writing the resource would be a breeze.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create public subnets
resource "aws_subnet" "public" {
  count  = var.preferred_number_of_public_subnets == null ? length(data.aws_availability_zones.available.names) : var.preferred_number_of_public_subnets   
  vpc_id = aws_vpc.main.id
  cidr_block              = cidrsubnet(var.vpc_cidr, 4 , count.index)
  map_public_ip_on_launch = true
  availability_zone       = data.aws_availability_zones.available.names[count.index]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final &lt;code&gt;main.tf&lt;/code&gt; file would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/uHqxvmc7uDBgp28js9s03fZaK6ZKSfw-K25MdQidM4I/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvbno5/enkxYjl6YnhjYTF0/Z3AzNTUucG5n" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/uHqxvmc7uDBgp28js9s03fZaK6ZKSfw-K25MdQidM4I/w:880/mb:500000/ar:1/aHR0cHM6Ly9kZXYt/dG8tdXBsb2Fkcy5z/My5hbWF6b25hd3Mu/Y29tL3VwbG9hZHMv/YXJ0aWNsZXMvbno5/enkxYjl6YnhjYTF0/Z3AzNTUucG5n" alt="main-tf" width="880" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm sure you noticed the private subnets have not been created. On the next publication, you would move on with creating more resources while also refactoring your code. "Doing is the best way of learning", that is exactly what is going to happen in this project.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="https://www.darey.io/"&gt;Darey.io&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
      <category>iac</category>
    </item>
  </channel>
</rss>
