<?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: Brian Mengo</title>
    <description>The latest articles on DEV Community by Brian Mengo (@brian_mengo).</description>
    <link>https://dev.to/brian_mengo</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%2F3844844%2F4aab0841-36fc-4e8f-90f3-a3ded6483e33.jpg</url>
      <title>DEV Community: Brian Mengo</title>
      <link>https://dev.to/brian_mengo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brian_mengo"/>
    <language>en</language>
    <item>
      <title>AWS Terraform Type Constarints</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Sun, 10 May 2026 15:21:19 +0000</pubDate>
      <link>https://dev.to/brian_mengo/aws-terraform-type-constarints-gnd</link>
      <guid>https://dev.to/brian_mengo/aws-terraform-type-constarints-gnd</guid>
      <description>&lt;p&gt;Today, I learned about Terraform type constraints and why they are essential for writing safe, predictable, and maintainable infrastructure code.&lt;/p&gt;

&lt;p&gt;Terraform variables are not just about passing values. With type constraints, variables become contracts that define what kind of data is allowed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topics Covered&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Primitive types:&lt;/strong&gt; &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collection types:&lt;/strong&gt; &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural types:&lt;/strong&gt; &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;object&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type validation and constraints&lt;/li&gt;
&lt;li&gt;Defining complex variable structures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Type Constraints Matter&lt;/strong&gt;&lt;br&gt;
Without type constraints, Terraform treats variables as loosely typed. This can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime errors during &lt;code&gt;terraform apply&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Unexpected values passed to resources&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard-to-debug infrastructure issues&lt;br&gt;
Using type constraints gives you:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Early validation at &lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Self-documenting variables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safer and predictable infrastructure code&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Primitive Type&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Number&lt;/strong&gt;&lt;br&gt;
Supports both integers and floating-point values.&lt;br&gt;
&lt;strong&gt;example&lt;/strong&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_count"&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;number&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Specifying the type as number restricts the variable to numeric values, matching Terraform’s expectations for count&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;String&lt;/strong&gt;&lt;br&gt;
A string is used for text-based values such as names, regions, or identifiers.&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&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;"region"&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;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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;String values must be enclosed in double quotes and can contain spaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boolean&lt;/strong&gt;&lt;br&gt;
A boolean represents &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. It is commonly used for feature toggles.&lt;br&gt;
&lt;strong&gt;example&lt;/strong&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;"monitoring_enabled"&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;bool&lt;/span&gt;
  &lt;span class="nx"&gt;default&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;&lt;strong&gt;Complex Types in Terraform&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;List&lt;/strong&gt;&lt;br&gt;
 A list is an ordered collection of values of the same type&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;"availability_zones"&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;list&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;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1b"&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;&lt;strong&gt;Set&lt;/strong&gt;&lt;br&gt;
A set is similar to a list, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Values must be unique&lt;/li&gt;
&lt;li&gt;Order is not guaranteed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Commonly used for Security-groups;&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;"allowed_ports"&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;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;443&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;&lt;strong&gt;Map&lt;/strong&gt;&lt;br&gt;
A key-value structure frequently used for tagging AWS resources.&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;"tag"&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;map&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;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&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="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev-EC2-instance"&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;Structural Types(Advanced)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Object&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object is a collection of named attributes with different data types, defined with keys.&lt;/li&gt;
&lt;li&gt;Example object variable config with three attributes:
&lt;/li&gt;
&lt;/ul&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;"config"&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;region&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;monitoring&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
    &lt;span class="nx"&gt;instance_count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&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-east-1"&lt;/span&gt;
    &lt;span class="nx"&gt;monitoring&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;instance_count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;&lt;strong&gt;Tuple&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tuple enables grouping multiple values with different data types in a fixed sequence.&lt;/li&gt;
&lt;li&gt;Example tuple variable with three elements (number, string, number):
&lt;/li&gt;
&lt;/ul&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;"ingress_values"&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;tuple&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;number&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;number&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"TCP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;443&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;&lt;strong&gt;Best practice I learnt when using type contraints;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use primitives for simple values.&lt;/li&gt;
&lt;li&gt;Use complex types to group multiple related values, especially when types vary.&lt;/li&gt;
&lt;li&gt;Understand indexing rules: lists and tuples are indexed; sets are not.&lt;/li&gt;
&lt;li&gt;Use objects for structured data with named fields of different types.&lt;/li&gt;
&lt;li&gt;Use maps for homogeneous key-value pairs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/gu2oCJ9DQiQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Terraform File Structures</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Sun, 10 May 2026 10:19:51 +0000</pubDate>
      <link>https://dev.to/brian_mengo/terraform-file-structures-5cen</link>
      <guid>https://dev.to/brian_mengo/terraform-file-structures-5cen</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Today we focus on file structure and organising Terraform projects. Initially all resources were placed in a single &lt;code&gt;main.tf&lt;/code&gt; file to simplify the learning process. What we are doing now is to improve the project structure by splitting resources and configurations into multiple files for better readability, collaboration and maintainablity.&lt;br&gt;
The root directory of a Terraform project is called the root module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform File Loading&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
There is no strict mandatory naming convention for Terraform files.recommendations come from HashiCorp best practices but are flexible.&lt;br&gt;
How Terraform loads files;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Terraform loads all &lt;code&gt;.tf&lt;/code&gt; files in the current directory&lt;/li&gt;
&lt;li&gt;Files are loaded in lexicographical order (alphabetical)&lt;/li&gt;
&lt;li&gt;All &lt;code&gt;.tf&lt;/code&gt; files are merged into a single configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Recommended File Structure and Best Practices&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-root/
├── backend.tf           # Backend configuration
├── provider.tf          # Provider configurations
├── variables.tf         # Input variable definitions
├── locals.tf           # Local value definitions
├── main.tf             # Main resource definitions
├── vpc.tf              # VPC-related resources
├── security.tf         # Security groups, NACLs
├── compute.tf          # EC2, Auto Scaling, etc.
├── storage.tf          # S3, EBS, EFS resources
├── database.tf         # RDS, DynamoDB resources
├── outputs.tf          # Output definitions
├── terraform.tfvars   # Variable values
└── README.md           # Documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common recommended files in the root module include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;main.tf:&lt;/strong&gt; Contains primary resource definitions such as S3, VPC, EC2, etc. Alternatively, resources may be further subdivided into files named after the resource type (e.g., &lt;code&gt;s3.tf&lt;/code&gt;, &lt;code&gt;vpc.tf&lt;/code&gt;, &lt;code&gt;ec2.tf&lt;/code&gt;), but this can become complex with many resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;variables.tf:&lt;/strong&gt; Dedicated file for input variable declarations (moved out from main.tf).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;outputs.tf:&lt;/strong&gt; File for output declarations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;providers.tf:&lt;/strong&gt; Contains provider configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backend.tf:&lt;/strong&gt; Contains backend configuration for state management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;terraform.tfvars:&lt;/strong&gt; File for input variable values (sensitive values should not be committed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;terraform.tfvars.example:&lt;/strong&gt; Template file for variable values to be shared publicly without exposing secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.gitignore:&lt;/strong&gt; To exclude sensitive or unnecessary files from being committed to version control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;README:&lt;/strong&gt; Documentation file.
&lt;strong&gt;Key best practice:&lt;/strong&gt; Do not commit &lt;code&gt;.tfvars&lt;/code&gt; files containing secrets or sensitive values to GitHub; instead, commit a &lt;code&gt;.example&lt;/code&gt; template.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;.gitignore Configuration and Files to Exclude&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;.gitignore&lt;/code&gt; file should exclude:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.terraform/&lt;/code&gt; directory (Terraform metadata, plugins, and cache)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*.tfstate&lt;/code&gt; and &lt;code&gt;*.tfstate.backup&lt;/code&gt; files (Terraform state files)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.terraform.lock.hcl&lt;/code&gt; (provider dependency lock file)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*.log&lt;/code&gt; files (e.g., crash logs)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt; and any &lt;code&gt;*.tfvars.json&lt;/code&gt; files (to avoid publishing sensitive data)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;These exclusions protect sensitive information and prevent unnecessary files from cluttering the repository.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced Project Structures and Environment Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple environments:&lt;/strong&gt; Separate folders or configurations for &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;, each with distinct &lt;code&gt;main.tf&lt;/code&gt; files.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environments/
├── dev/
│   ├── backend.tf
│   ├── terraform.tfvars
│   └── main.tf
├── staging/
│   ├── backend.tf
│   ├── terraform.tfvars
│   └── main.tf
└── production/
    ├── backend.tf
    ├── terraform.tfvars
    └── main.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modularisation:&lt;/strong&gt; Using modules for logically grouped resources, e.g., networking, compute, security modules.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modules/
├── vpc/
├── security/
└── compute/

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

&lt;/div&gt;


&lt;p&gt;Another approach is to use the same Terraform configuration files for all environments but supply different &lt;code&gt;terraform.tfvars&lt;/code&gt; files for each environment to inject environment-specific values.&lt;/p&gt;

&lt;p&gt;Terraform should be readable first, functional second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 6 helped me understand something deeper:&lt;/strong&gt;&lt;br&gt;
Good Terraform isn’t just about writing code—it’s about organizing it.&lt;/p&gt;

&lt;p&gt;A clean structure makes your infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to maintain&lt;/li&gt;
&lt;li&gt;Easier to scale&lt;/li&gt;
&lt;li&gt;Easier for team to collaborate&lt;/li&gt;
&lt;li&gt;Easier to troubleshoot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the video that helped me understand this concept;&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/QMsJholPkDY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>devops</category>
      <category>terraform</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Terraform Variables - Input Vs Output Vs Local Variables</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Mon, 04 May 2026 00:26:32 +0000</pubDate>
      <link>https://dev.to/brian_mengo/terraform-variables-input-vs-output-vs-local-variables-16h2</link>
      <guid>https://dev.to/brian_mengo/terraform-variables-input-vs-output-vs-local-variables-16h2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Purpose of Variables in Terraform&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Variables prevent repetitive hardcoding of values in Terraform configuration files.&lt;/li&gt;
&lt;li&gt;They reduce errors due to inconsistent value entries across multiple resources.&lt;/li&gt;
&lt;li&gt;Simplify updating environment-specific configurations (e.g., changing from &lt;code&gt;dev&lt;/code&gt; to &lt;code&gt;stage&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Types of Variables Based on Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input Variables:&lt;/strong&gt; Accept values from users or other sources.&lt;br&gt;
&lt;strong&gt;Output Variables:&lt;/strong&gt; Display or pass resource attributes after creation.&lt;br&gt;
&lt;strong&gt;Locals:&lt;/strong&gt; Define reusable, local values within a Terraform module for simplification and consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variable Types Based on Value&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primitive Types:&lt;/strong&gt; &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;(boolean).&lt;br&gt;
&lt;strong&gt;Complex Types:&lt;/strong&gt; &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;object&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Special Types:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;null&lt;/code&gt; (no specific type defined).&lt;br&gt;
&lt;code&gt;any&lt;/code&gt; (auto-detects type based on assigned value).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variable Declaration Syntax&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Basic format:&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;"environment"&lt;/span&gt; &lt;span class="p"&gt;{&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;"dev"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accessing variables in Terraform uses the syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For simple reference: &lt;code&gt;var.environment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For string interpolation: &lt;code&gt;"${var.environment}-bucket"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Locals Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Locals are defined using the locals block to store computed or concatenated values.&lt;br&gt;
Example:&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="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&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;environment&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-bucket"&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;Output Variables&lt;/strong&gt;&lt;br&gt;
Output variables allow capturing and displaying resource attributes after Terraform applies changes.&lt;br&gt;
Example declaration:&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;"vpc_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_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Variable Precedence in Terraform&lt;/strong&gt;&lt;br&gt;
Terraform supports multiple methods to assign values to variables. These methods have a clear precedence hierarchy from lowest to highest:&lt;/p&gt;

&lt;p&gt;1 (Lowest) Default value in &lt;code&gt;variable&lt;/code&gt; block - Value assigned within the variable declaration as &lt;code&gt;default&lt;/code&gt;.&lt;br&gt;
2   Environment variables prefixed with &lt;code&gt;TF_VAR_&lt;/code&gt; - Shell environment variables such as &lt;code&gt;export TF_VAR_environment=stage&lt;/code&gt;.&lt;br&gt;
3   Variable definition files (&lt;code&gt;.tfvars&lt;/code&gt; or &lt;code&gt;.tfvars.json&lt;/code&gt;) - Separate files like &lt;code&gt;terraform.tfvars&lt;/code&gt; with key-value pairs.&lt;br&gt;
4 (Highest) Command-line flags (&lt;code&gt;-var&lt;/code&gt;, &lt;code&gt;-var-file&lt;/code&gt;) - Values passed directly during &lt;code&gt;terraform plan&lt;/code&gt; or &lt;code&gt;terraform apply&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using environment variables or command-line flags allows dynamic overrides without changing Terraform files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.tfvars&lt;/code&gt; files are preferred for organising variables when multiple environments or parameter sets are used.&lt;/li&gt;
&lt;li&gt;Sensitive data (e.g., credentials) should be managed carefully, preferably using secret management tools instead of environment variables or command-line flags to avoid exposure in shell history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices and Recommendations&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use variables and locals to improve code reusability, consistency, and maintainability.&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;.tfvars&lt;/code&gt; files for variable management in multi-environment setups.&lt;/li&gt;
&lt;li&gt;Use output variables to expose important resource attributes for downstream use.&lt;/li&gt;
&lt;li&gt;Validate resource names and types against the latest Terraform AWS provider documentation.&lt;/li&gt;
&lt;li&gt;Manage sensitive variables securely outside of Terraform files.&lt;/li&gt;
&lt;li&gt;Clean up resources after testing with &lt;code&gt;terraform destroy -auto-approve&lt;/code&gt; to avoid unnecessary costs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/V-2yC39BONc"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>aws</category>
      <category>variables</category>
      <category>terraform</category>
      <category>iac</category>
    </item>
    <item>
      <title>Terraform State File Management with Remote Backend</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Fri, 01 May 2026 03:05:48 +0000</pubDate>
      <link>https://dev.to/brian_mengo/terraform-state-file-management-with-remote-backend-4p95</link>
      <guid>https://dev.to/brian_mengo/terraform-state-file-management-with-remote-backend-4p95</guid>
      <description>&lt;p&gt;On day 4 of my learning journey I learnt  how Terraform remembers what it creates, and how to manage that memory safely using a remote backend.&lt;/p&gt;

&lt;p&gt;When running &lt;code&gt;terraform apply&lt;/code&gt;, a file named &lt;strong&gt;terraform.tfstate&lt;/strong&gt; is generated in the working directory.&lt;br&gt;
This file is critical because it stores metadata that Terraform uses to track infrastructure resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Remote State Matters&lt;/strong&gt;&lt;br&gt;
When Terraform runs, it keeps track of infrastructure in a state file.&lt;/p&gt;

&lt;p&gt;If that file stays on a local machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s not shareable&lt;/li&gt;
&lt;li&gt;It’s not safe&lt;/li&gt;
&lt;li&gt;It can easily get corrupted or lost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;StateFile Best Practices&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Store StateFile to a Remote Backend:&lt;/em&gt; The problem with Statefile is it also contains all the important information like configuration, access keys and other sensitive information. So we shouldn't log that to a github or any other personal folders. It is better to keep that in a Remote Backend like S3 in AWS, Blob in Azure and GCP Cloud Staorage.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do Not Update/Delete StateFile:&lt;/em&gt; StateFile will always be generated by Terraform. You should not make any manual changes to that file or shouldn't delete them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;State Locking:&lt;/em&gt; Just imagine there is a StateFile and 2 devops engineers tries to modify or create infra using that file with different changes. This will corrupt StateFile. So It should be locked in such a way until first user completes terraform apply, then it should be unlocked and second user should apply his changes after that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Isolation of StateFile:&lt;/em&gt; StateFile should be isolated for multiple environments in a different folder. Not all StateFile should be combined with a same name or in a same folder.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Regular Backup:&lt;/em&gt; It is essential to take regular backup's of a StateFile as we cannot access them in case of Global outages. So Enable Versioning on AWS S3 Buckets and also setup policies to store older StateFiles to a different account or tar them to other location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend Configuration Details&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The S3 bucket used for state storage must already exist before initializing Terraform.&lt;/li&gt;
&lt;li&gt;The bucket is not created by Terraform itself because it must be available to store the state file before Terraform runs.&lt;/li&gt;
&lt;li&gt;Creating the bucket manually can be done via AWS CLI, AWS Console, or CI/CD pipelines.&lt;/li&gt;
&lt;li&gt;Avoid including the bucket creation in Terraform resources to prevent circular dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Configured Remote Backend&lt;/strong&gt;&lt;br&gt;
I updated my Terraform configuration to use S3 as backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&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="s2"&gt;"my-terraform-state-bucket"&lt;/span&gt;
  &lt;span class="nx"&gt;key&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"day-04/dev/terraform.tfstate"&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-east-1"&lt;/span&gt;
  &lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;encrypt&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;&lt;strong&gt;Observing Remote State File Behaviour&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When running &lt;code&gt;terraform plan&lt;/code&gt; or &lt;code&gt;terraform apply&lt;/code&gt;, no state file is created locally except a minimal metadata file.&lt;/li&gt;
&lt;li&gt;The actual state file is stored inside the S3 bucket under the specified key (e.g.,&lt;code&gt;dev/terraform.tfstate&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The remote state file is a JSON file containing all resource details, including some encoded and sensitive information.&lt;/li&gt;
&lt;li&gt;This setup improves security by avoiding sensitive state information on local machines and centralising management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verified state in S3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2zfmbknq7qed80pinqd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2zfmbknq7qed80pinqd.png" alt="terraform.tfstate file" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managing Terraform State&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Terraform provides commands to manage state without manual JSON editing:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform state list&lt;/code&gt;       Lists resources in the state file&lt;br&gt;
&lt;code&gt;terraform state show&lt;/code&gt;     Shows detailed info about a specific resource&lt;br&gt;
&lt;code&gt;terraform state rm&lt;/code&gt;   Removes a resource from the state file (safe method)&lt;br&gt;
&lt;code&gt;terraform state pull&lt;/code&gt;   Fetches the current state file from backend&lt;/p&gt;

&lt;p&gt;These commands help manage the state file programmatically and safely.&lt;/p&gt;

&lt;p&gt;Below is the Youtube Video for reference: Tech Tutorials with Piyush — “Terraform StateFile Management with S3”&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/YsEdrl9O5os"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>statefile</category>
      <category>terraform</category>
      <category>iac</category>
      <category>devops</category>
    </item>
    <item>
      <title>Creating AWS S3 Bucket using Terraform</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Sun, 26 Apr 2026 11:36:04 +0000</pubDate>
      <link>https://dev.to/brian_mengo/creating-aws-s3-bucket-using-terraform-4f6k</link>
      <guid>https://dev.to/brian_mengo/creating-aws-s3-bucket-using-terraform-4f6k</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
The first resource I create and provision using terraform is the AWS S3 bucket. By writing terraform configuration files (&lt;code&gt;.tf files&lt;/code&gt;) to initialise providers and use terraform commands to interact with AWS APIs and provision resources.&lt;/p&gt;

&lt;p&gt;AWS CLI for credentials setup before creating any resource in AWS using &lt;code&gt;aws configure&lt;/code&gt;.&lt;br&gt;
The below image shows the procedure of provisioning a simple S3 Bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F880oxzuj9m4hyhm7mcja.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F880oxzuj9m4hyhm7mcja.webp" alt=" " width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform Configuration&lt;/strong&gt;&lt;br&gt;
The set up for this resource involves only two block: the provider configuration block and the S3 bucket resource block&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Provider Block&lt;/strong&gt;&lt;br&gt;
Since we are using the AWS provider we setup by specifying the region in which the resource will be created&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-east-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;S3 Bucket Resource Block&lt;/strong&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;"demo_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="s2"&gt;"devbrio53-store"&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;The Terraform resource block starts with the keyword resource, followed by the resource type &lt;code&gt;aws_s3_bucket&lt;/code&gt; and a user-defined resource name (e.g., &lt;code&gt;first_bucket&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The bucket name must be &lt;strong&gt;globally unique across AWS regions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tags are added as a nested block with key-value pairs, e.g., &lt;code&gt;Name&lt;/code&gt; and &lt;code&gt;Environment&lt;/code&gt;&lt;br&gt;
Tags are strings enclosed in double quotes and enclosed within curly braces, representing a map/dictionary data type in Terraform.&lt;/p&gt;

&lt;p&gt;Using Terraform AWS provider documentation to find the correct resource block for an S3 bucket (&lt;code&gt;aws_s3_bucket&lt;/code&gt;).&lt;br&gt;
The documentation provides example usage, argument references (mandatory and optional parameters), and guides how to customise the resource block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running Terraform Commands to Provision the Bucket&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Terraform initialisation is run using the 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 init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This downloads the necessary provider plugins and initialises the backend.&lt;/p&gt;

&lt;p&gt;Next, a plan is created using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This performs a dry run to preview the changes Terraform will apply without actually creating or modifying resources.&lt;/p&gt;

&lt;p&gt;The command to apply the changes and create the bucket is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform prompts for confirmation before applying changes; typing yes proceeds with the creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running terraform plan again shows&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero resources to add&lt;/li&gt;
&lt;li&gt;One resource to change&lt;/li&gt;
&lt;li&gt;Zero resources to destroy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform performs a state comparison between the current AWS environment and the configuration file to detect changes.&lt;/p&gt;

&lt;p&gt;To delete the created bucket and clean up resources, the command is:&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;This removes everything created by the Terraform configuration. It’s a handy way to keep your AWS account clean while learning.&lt;/p&gt;

&lt;p&gt;Today’s learning wasn’t just about creating an S3 bucket.&lt;/p&gt;

&lt;p&gt;It was about understanding how Terraform connects with AWS, and why authentication is the foundation of everything in cloud.&lt;/p&gt;

&lt;p&gt;A simple bucket  but a meaningful step forward.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/09HQ_R1P7Lw"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3bucket</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>Terraform AWS Provider</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Thu, 23 Apr 2026 07:27:21 +0000</pubDate>
      <link>https://dev.to/brian_mengo/terraform-aws-provider-2f3m</link>
      <guid>https://dev.to/brian_mengo/terraform-aws-provider-2f3m</guid>
      <description>&lt;p&gt;&lt;strong&gt;How Terraform Talks to the Cloud&lt;/strong&gt;&lt;br&gt;
We begin with an introductory concept of &lt;strong&gt;Terraform providers&lt;/strong&gt;, which is basically a plugin bridging Terraform and cloud providers.&lt;br&gt;
Providers translate Terraform's HCL (HashiCorp Configuration Language) code into API calls understood by cloud platforms like AWS, Azure, or GCP. &lt;br&gt;
When provisioning a resource (e.g., an AWS S3 bucket), Terraform interacts with the cloud provider’s API via the corresponding provider plugin.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnaxzb2xh67kgvtvq0ina.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnaxzb2xh67kgvtvq0ina.png" alt=" " width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role and Function of Terraform Providers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq0nf28h7t1tch9l1vpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsq0nf28h7t1tch9l1vpu.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The provider plugin is responsible for translating Terraform’s configuration into API requests for the target service.&lt;br&gt;
Terraform providers thus enable infrastructure as code by connecting declarative Terraform files with underlying API operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of Terraform Providers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are three main categories of Terraform providers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Official providers&lt;/strong&gt;: Maintained by the cloud providers themselves (e.g., AWS, Azure, GCP).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partner providers&lt;/strong&gt;: Maintained by third-party organisations, not the cloud providers directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community providers&lt;/strong&gt;: Maintained by the open-source community. Providers can target cloud APIs or other services such as Docker, Kubernetes, Prometheus, and Grafana.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Exploring Terraform AWS Provider Documentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users are encouraged to visit the official Terraform AWS provider page on the Terraform Registry (registry.terraform.io).&lt;br&gt;
This page lists all AWS services supported by the provider, enabling provisioning across a broad range of AWS infrastructure components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importance of Version Locking and Compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the latest Terraform or provider versions by default can cause compatibility issues if your Terraform code is not tested against those versions.&lt;/li&gt;
&lt;li&gt;Version locking ensures stability by using the tested combination of Terraform core and provider versions.&lt;/li&gt;
&lt;li&gt;Upgrading versions should be done cautiously: test in non-production environments before applying to production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Understanding Version Constraints and Operators&lt;/strong&gt;&lt;br&gt;
Terraform supports several operators for version constraints:&lt;br&gt;
Operator Meaning;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;=&lt;/strong&gt;  Exact version match only&lt;br&gt;
 &lt;strong&gt;!=&lt;/strong&gt;   Excludes the specified version&lt;br&gt;
&lt;strong&gt;&amp;lt;, &amp;lt;=&lt;/strong&gt; Allows versions less than (or equal to) the specified version&lt;br&gt;
&lt;strong&gt;&amp;gt;, &amp;gt;=&lt;/strong&gt; Allows versions greater than (or equal to) the specified version&lt;br&gt;
&lt;strong&gt;~&amp;gt;&lt;/strong&gt; (Tilde Greater Than) Allows patch-level updates within the specified minor version (e.g., ~&amp;gt; 6.7.0 allows any version &amp;gt;= 6.7.0 but &amp;lt; 6.8.0)&lt;/p&gt;

&lt;p&gt;The tilde operator ~&amp;gt; is commonly used to allow patch upgrades without crossing minor or major version boundaries, preserving compatibility.&lt;br&gt;
Examples:&lt;br&gt;
~&amp;gt; 6.7.0 allows versions 6.7.1, 6.7.2, etc., but not 6.8.0.&lt;br&gt;
~&amp;gt; 1.0 allows versions 1.1, 1.2, etc., but not 2.0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a Basic Terraform Provider Configuration&lt;/strong&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="c1"&gt;# Configure the AWS Provider&lt;/span&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-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 6.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="c1"&gt;# Create a VPC&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Terraform code tells Terraform to use the AWS provider and makes sure it uses a stable version of it. It then sets the AWS region to us-east-1, which means all resources will be created in that location. Finally, the code creates a VPC, which is like a private network inside AWS where you can later add servers, subnets, and other resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform Init&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running terraform init or tf init downloads the necessary provider plugins and initialises Terraform in the working directory.&lt;/li&gt;
&lt;li&gt;The provider plugin is downloaded automatically based on the system OS (Mac, Windows, Linux).&lt;/li&gt;
&lt;li&gt;This step prepares Terraform to interact with the configured provider APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Running terraform plan and Understanding its Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;terraform plan compares the current Terraform configuration with the real infrastructure state.&lt;br&gt;
The plan shows which resources will be created, changed, or destroyed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication with AWS CLI&lt;/strong&gt;&lt;br&gt;
Terraform requires valid AWS credentials to interact with AWS services.&lt;br&gt;
The simplest authentication method is running aws configure (AWS CLI tool) to input:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Key ID&lt;/li&gt;
&lt;li&gt;AWS Secret Access Key&lt;/li&gt;
&lt;li&gt;Default region
These credentials can be generated from the AWS Management Console under IAM users, with appropriate permissions (e.g., S3 full access).
Credentials stored by AWS CLI are then used by Terraform automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices I Learned&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;✔ Always specify provider versions&lt;/strong&gt;&lt;br&gt;
Never rely on defaults.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Use version ranges (not just exact versions)&lt;/strong&gt;&lt;br&gt;
Keeps things safe but flexible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Test upgrades in a lower environment&lt;/strong&gt;&lt;br&gt;
Never update versions directly in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Use terraform providers lock&lt;/strong&gt;&lt;br&gt;
It creates a .terraform.lock.hcl file to ensure consistent builds.&lt;/p&gt;

&lt;p&gt;This makes your infrastructure “version-proof”.&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/JFiMmaktnuM"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
      <category>aws</category>
    </item>
    <item>
      <title>Introduction to IAC, how Terraform Works- Day01</title>
      <dc:creator>Brian Mengo</dc:creator>
      <pubDate>Tue, 21 Apr 2026 14:59:00 +0000</pubDate>
      <link>https://dev.to/brian_mengo/introduction-to-iac-how-terraform-works-day01-35lk</link>
      <guid>https://dev.to/brian_mengo/introduction-to-iac-how-terraform-works-day01-35lk</guid>
      <description>&lt;p&gt;Day01 of my 30day AWS terraform challenge, and I begin with highlighting what IaC is and how teams are using it to manage infrastructure in the cloud. &lt;br&gt;
Infrastructure as Code (IaC) is the practice of managing and provisioning computing infrastructure through machine-readable configuration files rather than through manual processes or interactive configuration tools.&lt;br&gt;
Think of it like this: instead of clicking through a cloud console to spin up servers, databases, and networks, you write code that describes exactly what you want — and a tool builds it for you.&lt;/p&gt;

&lt;p&gt;Tools for Infrastrucure as Code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform (Multi-cloud and widely used)&lt;/li&gt;
&lt;li&gt;Pulumi&lt;/li&gt;
&lt;li&gt;AWS CloudFormation, AWS CDK, AWS SAM&lt;/li&gt;
&lt;li&gt;Azure ARM / Bicep&lt;/li&gt;
&lt;li&gt;GCP Deployment Manager, GCP Config Controller&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is Terraform&lt;/strong&gt;&lt;br&gt;
Terraform is an open-source IaC tool created by HashiCorp. It allows you to define, preview, and deploy infrastructure across multiple cloud providers — AWS, Azure, Google Cloud, and hundreds more — using a simple, human-readable language called HCL (HashiCorp Configuration Language).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26duckq3akmpbnxjqw2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26duckq3akmpbnxjqw2k.png" alt=" " width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual provisioning of Infrastructure Challenges&lt;/strong&gt;;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time-consuming: A simple three-tier app infrastructure can take around  2 hours to set up manually.&lt;/li&gt;
&lt;li&gt;Complexity grows exponentially when managing multiple environments&lt;/li&gt;
&lt;li&gt;Human error risks: Manual steps increase chances of misconfiguration, security oversights, or inconsistent environments&lt;/li&gt;
&lt;li&gt;Inconsistency: Different people provisioning environments can lead to "it works on my machine" issues.&lt;/li&gt;
&lt;li&gt;High operational costs and delays affecting dependent teams &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;Benefits of Terraform&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automates the process.&lt;/li&gt;
&lt;li&gt;Reduces time needed to perform the same action again and again.&lt;/li&gt;
&lt;li&gt;Reduces labour resource which was needed to manual perform the process.&lt;/li&gt;
&lt;li&gt;Reduces the chances of human error.&lt;/li&gt;
&lt;li&gt;We can track changes using git.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Terraform Works&lt;/strong&gt;&lt;br&gt;
Terraform Initialise - Run terraform init to initialize the working directory and download necessary providers.&lt;br&gt;
Validate Configuraion - Run terraform validate to check for syntax or configuration errors.&lt;br&gt;
Terraform Plan - Run terraform plan to preview infrastructure changes before applying.&lt;br&gt;
Terraform apply - Run terraform apply to provision or modify the infrastructure by calling cloud API.&lt;br&gt;
Terraform Destroy - Run terraform destroy to delete resources when no longer needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nq5yjt6blsr47a36siu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nq5yjt6blsr47a36siu.png" alt=" " width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Terraform&lt;/strong&gt; → &lt;a href="http://developer.hashicorp.com/terraform/install" rel="noopener noreferrer"&gt;developer.hashicorp.com/terraform/install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up a cloud provider account&lt;/strong&gt; (AWS Free Tier is great for learning)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write your first &lt;code&gt;.tf&lt;/code&gt; file&lt;/strong&gt; and run &lt;code&gt;terraform init&lt;/code&gt;, &lt;code&gt;terraform plan&lt;/code&gt;, &lt;code&gt;terraform apply&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore the Terraform Registry&lt;/strong&gt; → &lt;a href="http://registry.terraform.io" rel="noopener noreferrer"&gt;registry.terraform.io&lt;/a&gt; for modules and providers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/s5fwSG_00P8"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

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