<?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>Forem: Deepak Sharma</title>
    <description>The latest articles on Forem by Deepak Sharma (@techmademi).</description>
    <link>https://forem.com/techmademi</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%2F3444954%2F3b4ebd6a-22c3-4c62-88be-78404b18e8da.png</url>
      <title>Forem: Deepak Sharma</title>
      <link>https://forem.com/techmademi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/techmademi"/>
    <language>en</language>
    <item>
      <title>🚀 Terraform Azure Infrastructure (Modular Architecture + DevSecOps)</title>
      <dc:creator>Deepak Sharma</dc:creator>
      <pubDate>Thu, 27 Nov 2025 06:17:02 +0000</pubDate>
      <link>https://forem.com/techmademi/terraform-azure-infrastructure-modular-architecture-devsecops-291p</link>
      <guid>https://forem.com/techmademi/terraform-azure-infrastructure-modular-architecture-devsecops-291p</guid>
      <description>&lt;h2&gt;
  
  
  Code Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── azure-pipelines.yml                 # Azure DevOps CI/CD pipeline 
├── main
│   ├── main.tf                         # Module orchestration
│   ├── provider.tf                     # Azure provider configuration
│   ├── terraform.tfvars                # Input variable values
│   └── variable.tf                     # Module variables
├── modules
│   ├── 01_resource_group               # Resource Group creation
│   ├── 02_storage_account              # Storage Accounts
│   ├── 03_storage_container            # Storage Containers
│   ├── 04-Public_IP                    # Public IP
│   ├── 05_Virtual_Net                  # VNet &amp;amp; Subnets
│   ├── 06_sql_server                   # Azure SQL Server
│   ├── 07_sql_database                 # Azure SQL Database
│   ├── 08_net_interface                # Network Interfaces
│   └── 09_Virtual_Machine              # Azure VM
└── README.md

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  3-Tier Terraform Infra + Azure Pipeline Architecture Diagram
&lt;/h2&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%2Ff0kiqvqzdebj22fmy63j.jpg" 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%2Ff0kiqvqzdebj22fmy63j.jpg" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Git Repository URL:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/deepak83s143/3-Tier-Application-Infra-with-SAST-Scanning-Azure-Pipeline.git" rel="noopener noreferrer"&gt;https://github.com/deepak83s143/3-Tier-Application-Infra-with-SAST-Scanning-Azure-Pipeline.git&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Modular Terraform structure&lt;/li&gt;
&lt;li&gt;Incremental resource creation&lt;/li&gt;
&lt;li&gt;Environment-based scalability&lt;/li&gt;
&lt;li&gt;Azure backend remote state configuration&lt;/li&gt;
&lt;li&gt;DevSecOps validation:&lt;/li&gt;
&lt;li&gt;Terraform Validation (terraform validate)

&lt;ul&gt;
&lt;li&gt;tfsec security scan&lt;/li&gt;
&lt;li&gt;tflint linting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Manual approval stage before provisioning&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Technologies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform — IaC provisioning&lt;/li&gt;
&lt;li&gt;AzureRM Provider&lt;/li&gt;
&lt;li&gt;Azure DevOps Pipeline&lt;/li&gt;
&lt;li&gt;tfsec — Static security scan&lt;/li&gt;
&lt;li&gt;tflint — Terraform linting and provider validation&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Terraform Workflow (Modules)
&lt;/h3&gt;

&lt;p&gt;The root main/main.tf orchestrates creation in dependency order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resource Group&lt;/li&gt;
&lt;li&gt;Storage Account&lt;/li&gt;
&lt;li&gt;Storage Container&lt;/li&gt;
&lt;li&gt;Public IP&lt;/li&gt;
&lt;li&gt;Virtual Network &amp;amp; Subnets&lt;/li&gt;
&lt;li&gt;SQL Server&lt;/li&gt;
&lt;li&gt;SQL Database&lt;/li&gt;
&lt;li&gt;Network Interface&lt;/li&gt;
&lt;li&gt;Virtual Machine&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each module accepts input variables and returns useful outputs such as IDs, names, and connection objects.&lt;/p&gt;




&lt;h3&gt;
  
  
  Remote State Backend
&lt;/h3&gt;

&lt;p&gt;Azure backend ensures centralized state storage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backendAzureRmResourceGroupName: "ResourceGroupName"
backendAzureRmStorageAccountName: "StorageAccountName
backendAzureRmContainerName: "StorageContainerName"
backendAzureRmKey: "KeyName"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Azure DevOps Pipeline Overview
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pipeline stages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integration&lt;/li&gt;
&lt;li&gt;Terraform init&lt;/li&gt;
&lt;li&gt;Terraform validate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SanityCheck&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tfsec security scan&lt;/li&gt;
&lt;li&gt;tflint recursive lint&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CodePlanning&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terraform plan&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ManualValidation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual approval by reviewer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;InfraCreation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terraform apply (auto approve)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  SAST Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;tfsec&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performs static vulnerability scanning&lt;/li&gt;
&lt;li&gt;Detects insecure Terraform configurations&lt;/li&gt;
&lt;li&gt;Ensures cloud compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Used with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task: tfsec@1
dir: $(System.DefaultWorkingDirectory)/main
version: v1.26.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;tflint&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates wrong resource types, regions, and deprecated resources&lt;/li&gt;
&lt;li&gt;Provider-specific rule sets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tflint --recursive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Variables &amp;amp; tfvars
&lt;/h3&gt;

&lt;p&gt;User inputs are stored in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main/variable.tf
main/terraform.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource Group configuration&lt;/li&gt;
&lt;li&gt;Storage details&lt;/li&gt;
&lt;li&gt;VNet CIDR blocks and subnet ranges&lt;/li&gt;
&lt;li&gt;SQL server credentials&lt;/li&gt;
&lt;li&gt;VM sizing and OS details&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note! :-&lt;/strong&gt; Never commit sensitive credentials to Git.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Follow module boundaries strictly&lt;/li&gt;
&lt;li&gt;No direct resource creation in main.tf&lt;/li&gt;
&lt;li&gt;Use tfsec &amp;amp; tflint before merge&lt;/li&gt;
&lt;li&gt;Always review plan outputs&lt;/li&gt;
&lt;li&gt;Store secrets in:

&lt;ul&gt;
&lt;li&gt;Azure KeyVault&lt;/li&gt;
&lt;li&gt;DevOps Library secure variables&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Designed for IaC repeatability&lt;/li&gt;
&lt;li&gt;Suitable for multi-environment deployments (dev/stg/prod)&lt;/li&gt;
&lt;li&gt;Scalable due to isolated Terraform modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Follow me on&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;a href="https://github.com/techmademi" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3291%2F3291695.png" alt="GitHub" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.linkedin.com/in/deepak83s143/" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3536%2F3536505.png" alt="LinkedIn" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.youtube.com/@MademiTech" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3670%2F3670147.png" alt="YouTube" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>architecture</category>
      <category>azure</category>
    </item>
    <item>
      <title>🚀 Azure Pipeline for Terraform Deployment (Dev &amp; Prod Environments)</title>
      <dc:creator>Deepak Sharma</dc:creator>
      <pubDate>Mon, 01 Sep 2025 08:20:33 +0000</pubDate>
      <link>https://forem.com/techmademi/azure-pipeline-4mhi</link>
      <guid>https://forem.com/techmademi/azure-pipeline-4mhi</guid>
      <description>&lt;p&gt;Managing infrastructure with Terraform is one of the most common practices in modern DevOps workflows. But when it comes to &lt;strong&gt;automation and governance&lt;/strong&gt;, Azure DevOps pipelines make the process much smoother.  &lt;/p&gt;

&lt;p&gt;In this blog, I’ll walk you through a &lt;strong&gt;real-world Azure DevOps pipeline&lt;/strong&gt; that deploys Terraform infrastructure to &lt;strong&gt;Dev&lt;/strong&gt; and &lt;strong&gt;Prod&lt;/strong&gt; environments with &lt;strong&gt;manual approvals&lt;/strong&gt; in between.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔑 Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before setting up this pipeline, make sure you have the following in place:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Active Azure Subscription&lt;/strong&gt;
You need a valid Azure subscription where your Terraform resources will be deployed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure DevOps Account&lt;/strong&gt;
An Azure DevOps project should be created to host your pipeline and repository.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Hosted Agent Pool&lt;/strong&gt;
A self-hosted agent is required to run Terraform tasks. This gives more control and avoids limitations of Microsoft-hosted agents.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App Registration with Federated Credentials&lt;/strong&gt;
Create an App Registration in Azure AD and configure it with &lt;strong&gt;federated credentials&lt;/strong&gt;. This will be used as the &lt;strong&gt;Service Connection (SPN)&lt;/strong&gt; in Azure DevOps to authenticate Terraform with Azure.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Code&lt;/strong&gt;
A working Terraform configuration (with &lt;code&gt;.tf&lt;/code&gt; files and &lt;code&gt;.tfvars&lt;/code&gt; for Dev and Prod) must be present in your repository.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📌 Pipeline Overview
&lt;/h2&gt;

&lt;p&gt;This pipeline is designed with two major stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dev Stage&lt;/strong&gt; → Runs Terraform &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, requires manual approval, and then applies changes on the Dev environment.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prod Stage&lt;/strong&gt; → After Dev is successful, it requires another manual approval and then applies changes to the Prod environment.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By using &lt;strong&gt;manual validations&lt;/strong&gt;, we ensure that no changes are applied accidentally in production without human approval.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Key Features of the Pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-stage deployment&lt;/strong&gt; → Dev first, then Prod.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform AzureRM backend&lt;/strong&gt; → Stores the Terraform state in an Azure Storage Account.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual validations&lt;/strong&gt; → Adds an approval step before applying changes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable variables&lt;/strong&gt; → Service connection, resource group, storage account, and container details are stored as variables to avoid repetition.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📝 Pipeline YAML
&lt;/h2&gt;

&lt;p&gt;Here’s the YAML code for the pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mademitech&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;serviceConnection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mademi-spn'&lt;/span&gt;
  &lt;span class="na"&gt;rgName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mademi-rg'&lt;/span&gt;
  &lt;span class="na"&gt;storageAccount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mademisg'&lt;/span&gt;
  &lt;span class="na"&gt;containerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mademistatefiles'&lt;/span&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dev&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate_Dev&lt;/span&gt;
        &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate on Dev&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTask@5&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Init Dev&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
              &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;init'&lt;/span&gt;
              &lt;span class="na"&gt;backendServiceArm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(serviceConnection)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmResourceGroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(rgName)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmStorageAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(storageAccount)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmContainerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(containerName)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev.tfstate'&lt;/span&gt;

          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTask@5&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Plan Dev&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
              &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;plan'&lt;/span&gt;
              &lt;span class="na"&gt;commandOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-var-file=dev.tfvars&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--lock=false'&lt;/span&gt;
              &lt;span class="na"&gt;environmentServiceNameAzureRM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(serviceConnection)&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation&lt;/span&gt;
        &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Manual Approval for Dev Deployment&lt;/span&gt;
        &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate_Dev&lt;/span&gt;
        &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;server&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation@1&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;notifyUsers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deepak83s143@gmail.com'&lt;/span&gt;
              &lt;span class="na"&gt;onTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resume'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy_Dev&lt;/span&gt;
        &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy on Dev&lt;/span&gt;
        &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTask@5&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Apply Dev&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
              &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apply'&lt;/span&gt;
              &lt;span class="na"&gt;commandOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-var-file=dev.tfvars&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--auto-approve&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--lock=false'&lt;/span&gt;
              &lt;span class="na"&gt;environmentServiceNameAzureRM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(serviceConnection)&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prod&lt;/span&gt;
    &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dev&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation_Prod&lt;/span&gt;
        &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Manual Approval for Prod&lt;/span&gt;
        &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;server&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation@1&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;notifyUsers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deepak83s143@gmail.com'&lt;/span&gt;
              &lt;span class="na"&gt;onTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resume'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy_Prod&lt;/span&gt;
        &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy on Prod&lt;/span&gt;
        &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ManualValidation_Prod&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTask@5&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Init Prod&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
              &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;init'&lt;/span&gt;
              &lt;span class="na"&gt;backendServiceArm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(serviceConnection)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmResourceGroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(rgName)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmStorageAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(storageAccount)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmContainerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(containerName)&lt;/span&gt;
              &lt;span class="na"&gt;backendAzureRmKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prod.tfstate'&lt;/span&gt;

          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTask@5&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Apply Prod&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
              &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apply'&lt;/span&gt;
              &lt;span class="na"&gt;commandOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-var-file=prod.tfvars&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--auto-approve'&lt;/span&gt;
              &lt;span class="na"&gt;environmentServiceNameAzureRM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(serviceConnection)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Step-by-Step Explanation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Trigger &amp;amp; Pool&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;trigger:
- master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline runs automatically whenever code is pushed to the master branch.&lt;br&gt;
The pool is set to mademitech, which means it will run on a self-hosted agent.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Variables&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;variables:
  serviceConnection: &lt;span class="s1"&gt;'mademi-spn'&lt;/span&gt;
  rgName: &lt;span class="s1"&gt;'mademi-rg'&lt;/span&gt;
  storageAccount: &lt;span class="s1"&gt;'mademisg'&lt;/span&gt;
  containerName: &lt;span class="s1"&gt;'mademistatefiles'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These variables store reusable values for the backend configuration.&lt;br&gt;
If tomorrow you change your storage account or service connection, you only need to update it once here.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;3. Dev Stage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Init&lt;/code&gt;&lt;/strong&gt;: Initializes Terraform with AzureRM backend and points to the Dev state file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Plan&lt;/code&gt;&lt;/strong&gt;: Runs terraform plan using dev.tfvars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Manual Validation&lt;/code&gt;&lt;/strong&gt;: Waits for approval before applying changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Apply&lt;/code&gt;&lt;/strong&gt;: Applies the infrastructure changes on Dev.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;4. Prod Stage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Depends on Dev&lt;/em&gt;&lt;/strong&gt; → Ensures that only after successful Dev deployment, Prod stage runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Manual Validation&lt;/em&gt;&lt;/strong&gt;: Extra safety check before deploying to Prod.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Init + Apply&lt;/em&gt;&lt;/strong&gt;: Runs Terraform init and applies changes using prod.tfvars.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ✅ Why This Approach?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Governance&lt;/em&gt;&lt;/strong&gt; → Manual approvals ensure no accidental changes hit production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Reusability&lt;/em&gt;&lt;/strong&gt; → Variables make the pipeline maintainable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Safety&lt;/em&gt;&lt;/strong&gt; → Dev is always tested first before Prod.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Automation + Control&lt;/em&gt;&lt;/strong&gt; → Combines Terraform automation with human oversight.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🎯 Final Thoughts
&lt;/h3&gt;

&lt;p&gt;This pipeline strikes a balance between automation and manual governance. It’s a solid starting point for teams looking to deploy infrastructure with Terraform while keeping production safe.&lt;/p&gt;

&lt;p&gt;From here, you can also enhance it by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding linting &amp;amp; validation steps before plan.&lt;/li&gt;
&lt;li&gt;Integrating policy checks with tools like Terraform Cloud or OPA.&lt;/li&gt;
&lt;li&gt;Using templates for even more reusability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Follow me on&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;a href="https://github.com/techmademi" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3291%2F3291695.png" alt="GitHub" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.linkedin.com/in/deepak83s143/" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3536%2F3536505.png" alt="LinkedIn" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.youtube.com/@MademiTech" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3670%2F3670147.png" alt="YouTube" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>cicd</category>
      <category>terraform</category>
    </item>
    <item>
      <title>🚀 Terraform Module Example – Resource Group Creation on Azure</title>
      <dc:creator>Deepak Sharma</dc:creator>
      <pubDate>Tue, 19 Aug 2025 11:05:25 +0000</pubDate>
      <link>https://forem.com/techmademi/terraform-module-example-resource-group-creation-on-azure-281</link>
      <guid>https://forem.com/techmademi/terraform-module-example-resource-group-creation-on-azure-281</guid>
      <description>&lt;p&gt;This project demonstrates how to create an &lt;strong&gt;Azure Resource Group&lt;/strong&gt; using &lt;strong&gt;Terraform modules&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
By using modules, we can organize our code better, promote reusability, and simplify management of infrastructure.&lt;/p&gt;


&lt;h2&gt;
  
  
  📂 Project Structure
&lt;/h2&gt;

&lt;p&gt;parent_module/&lt;br&gt;
│── main.tf&lt;br&gt;
│&lt;br&gt;
└── modules/&lt;br&gt;
└──── resource_group/&lt;br&gt;
├────── resource_group.tf&lt;br&gt;
├────── variables.tf&lt;/p&gt;


&lt;h2&gt;
  
  
  🔹 1. &lt;code&gt;main.tf&lt;/code&gt; (in parent_module directory)
&lt;/h2&gt;

&lt;p&gt;This is the &lt;strong&gt;root configuration&lt;/strong&gt; file where we call our module.&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;module&lt;/span&gt; &lt;span class="s2"&gt;"rg_create"&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;"../modules/resource_group"&lt;/span&gt;
  &lt;span class="nx"&gt;rg_name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mademi-rg1"&lt;/span&gt;
  &lt;span class="nx"&gt;rg_location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"centralus"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;module "rg_create"&lt;/code&gt; → Declares a module block named rg_create.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;source = "../modules/resource_group"&lt;/code&gt; → Points to the directory where our module is located.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rg_name&lt;/code&gt; → Resource Group name passed to the module (mademi-rg1).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rg_location&lt;/code&gt; → Azure region where the Resource Group will be created (centralus).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 2. resource_group.tf (inside modules/resource_group)
&lt;/h2&gt;

&lt;p&gt;This file defines the actual resource that Terraform will create.&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_resource_group"&lt;/span&gt; &lt;span class="s2"&gt;"mademi-rg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg_name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg_location&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;azurerm_resource_group&lt;/code&gt; → Azure Resource Group resource type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; → Uses the value of the variable rg_name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;location&lt;/code&gt; → Uses the value of the variable rg_location.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 3. variables.tf (inside modules/resource_group)
&lt;/h2&gt;

&lt;p&gt;This file declares the input variables that the module will accept.&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;variable&lt;/span&gt; &lt;span class="s2"&gt;"rg_name"&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"rg_location"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rg_name&lt;/code&gt; → The name of the Resource Group (string type).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rg_location&lt;/code&gt; → The Azure region (string type).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These variables are provided from the parent module (&lt;code&gt;main.tf&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ How to Run
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize Terraform (downloads Azure provider and module dependencies)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validate configuration&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Preview changes&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply changes (create resource group):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ✅ Final Output
&lt;/h2&gt;

&lt;p&gt;Terraform will create an Azure Resource Group named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mademi-rg1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the region:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  📘 Key Learning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Modules in Terraform make code reusable and clean.&lt;/li&gt;
&lt;li&gt;Instead of writing resources directly in the root main.tf, you can package them into modules and pass values as variables.&lt;/li&gt;
&lt;li&gt;This is especially useful when you manage large infrastructure with multiple environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;This setup can be extended further by adding&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual Networks&lt;/li&gt;
&lt;li&gt;Storage Accounts&lt;/li&gt;
&lt;li&gt;Virtual Machines&lt;/li&gt;
&lt;li&gt;and other Azure resources inside modules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Follow me on&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;a href="https://github.com/techmademi" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3291%2F3291695.png" alt="GitHub" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.linkedin.com/in/deepak83s143/" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3536%2F3536505.png" alt="LinkedIn" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;a href="https://www.youtube.com/@MademiTech" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-icons-png.flaticon.com%2F128%2F3670%2F3670147.png" alt="YouTube" width="128" height="128"&gt;
      &lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>terraform</category>
      <category>azure</category>
      <category>azuredevops</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
