<?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: Isaiah Izibili</title>
    <description>The latest articles on DEV Community by Isaiah Izibili (@isaiah_izibili_7a39b7d627).</description>
    <link>https://dev.to/isaiah_izibili_7a39b7d627</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%2F3283538%2Faa18e30c-0daf-4401-a0a1-4d9b644d7322.png</url>
      <title>DEV Community: Isaiah Izibili</title>
      <link>https://dev.to/isaiah_izibili_7a39b7d627</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/isaiah_izibili_7a39b7d627"/>
    <language>en</language>
    <item>
      <title>Building a Multi-Cloud Infrastructure with Terraform (AWS + Azure)</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Fri, 06 Mar 2026 01:41:13 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/building-a-multi-cloud-infrastructure-with-terraform-aws-azure-3efa</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/building-a-multi-cloud-infrastructure-with-terraform-aws-azure-3efa</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In modern cloud engineering, organizations increasingly adopt multi-cloud strategies to improve resilience, avoid vendor lock-in, and optimize cost.&lt;/p&gt;

&lt;p&gt;In this project, I designed and deployed infrastructure across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Web Services (AWS)&lt;/li&gt;
&lt;li&gt;Microsoft Azure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using a single Infrastructure as Code (IaC) tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🛠 Terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article explains the architecture, configuration, deployment steps, and lessons learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Architecture Overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AWS Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 Instance (Ubuntu Server)&lt;/li&gt;
&lt;li&gt;RDS MySQL Database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Azure Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource Group&lt;/li&gt;
&lt;li&gt;Virtual Network + Subnet&lt;/li&gt;
&lt;li&gt;Windows Virtual Machine&lt;/li&gt;
&lt;li&gt;IIS Web Server&lt;/li&gt;
&lt;li&gt;Public IP + NSG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All provisioned using Terraform providers for both clouds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Install Terraform&lt;/strong&gt;&lt;br&gt;
HashiCorp distributes Terraform as an executable CLI that you can install on supported operating systems, including Microsoft Windows, macOS, and several Linux distributions. You can also compile the Terraform CLI from source if a pre-compiled binary is not available for your system.&lt;/p&gt;

&lt;p&gt;If you use a package manager to install software on your macOS, Windows, or Linux system, you can use it to install Terraform. For this project, the focus will be on the Windows installation.&lt;/p&gt;

&lt;p&gt;Chocolatey &lt;a href="https://dev.tourl"&gt;https://chocolatey.org/&lt;/a&gt;is a free and open-source package management system for Windows. If you have Chocolatey installed, use it to install Terraform from your command line.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: HashiCorp does not maintain Chocolatey or the Terraform package. The latest version of Terraform is always available for you to download and install manually. Refer to the Manual installation tab below for instructions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Verify the Installation&lt;/strong&gt;&lt;br&gt;
Verify that the installation worked by opening a new terminal session and listing Terraform's available subcommands.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Install AWS CLI&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For Windows:&lt;/li&gt;
&lt;li&gt;Download the installer from AWS CLI official page (docs.aws.amazon.com in Bing).&lt;/li&gt;
&lt;li&gt;Run the .msi installer and follow the prompts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Verify installation with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F1priais30xs7yhax1wou.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%2F1priais30xs7yhax1wou.png" alt="aws version" width="800" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure AWS CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once installed, configure it with your credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Azure CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the installer from Microsoft’s official page.&lt;/li&gt;
&lt;li&gt;Run the .msi installer and follow the prompts.&lt;/li&gt;
&lt;li&gt;Verify installation:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi34alp2dvzp5rbffygni.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%2Fi34alp2dvzp5rbffygni.png" alt="AZ version" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Authenticate with Cloud Providers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AWS Login&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;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provide:&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 name (e.g., us-east-1)&lt;/li&gt;
&lt;li&gt;Default output format (e.g., json)&lt;/li&gt;
&lt;/ul&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%2F7syjgqhole7iyckqk5i9.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%2F7syjgqhole7iyckqk5i9.png" alt="AWs configure" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Your AWS Access key and ID must have been created in your AWS console. For security purpose we advise creating a USER and GROUP under IAM resources. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Azure Login&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;az login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;A browser window will open for you to authenticate with your Azure account.&lt;/li&gt;
&lt;li&gt;Once logged in, the terminal will display your subscription details.
Verify subscription:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az account show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F1w6zzarn24mc1zaw3bik.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%2F1w6zzarn24mc1zaw3bik.png" alt="AZ account show" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Define Terraform Providers
&lt;/h2&gt;

&lt;p&gt;Create terraform.tf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 5.0"
    }

    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~&amp;gt; 3.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

provider "azurerm" {
  features {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: terraform.tf is usually used for Terraform settings or backend configuration.&lt;br&gt;
What goes inside: Terraform version, Required providers, Backend configuration&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Create AWS and Azure Infrastructure
&lt;/h2&gt;

&lt;p&gt;Create main.tf (Complete Working Script):&lt;/p&gt;

&lt;p&gt;AWS Resources: EC2 Instance, AWS RDS MySQL Database, &lt;/p&gt;

&lt;p&gt;Azure Resources: Resource Group, Virtual Machine, Web Application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;############################################
# Get Latest Ubuntu 22.04 AMI
############################################
data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

############################################
# Create EC2 Instance
############################################
resource "aws_instance" "isaiah" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  tags = {
    Name = "isaiah"
  }
}
#Get default VPC
data "aws_vpc" "default" {
  default = true
}

#GET subnets in default VPC
data "aws_subnets" "default" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.default.id]
  }
}

#Create Security Group for RDS
resource "aws_security_group" "rds_sg" {
  name   = "isaiah-rds-sg"
  vpc_id = data.aws_vpc.default.id

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # ⚠️ for testing only
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

#Create RDS Module
module "db" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~&amp;gt; 6.0"

  identifier = "isaiah-demodb"

  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"   # cheaper for testing
  allocated_storage    = 20

  db_name  = "demodb"
  username = "isaiah"
  password = "IsaiahStrongPassword123!"   # change this
  port     = 3306

  publicly_accessible = true

  vpc_security_group_ids = [aws_security_group.rds_sg.id]

  create_db_subnet_group = true
  subnet_ids             = data.aws_subnets.default.ids

  family               = "mysql8.0"
  major_engine_version = "8.0"

  skip_final_snapshot = true
  deletion_protection = false

  tags = {
    Owner       = "Isaiah"
    Environment = "dev"
  }
}

#add random suffix
resource "random_string" "suffix" {
  length  = 5
  special = false
  upper   = false
}

#Resource group for Azure
resource "azurerm_resource_group" "isaiah_rg" {
  name     = "isaiah-webapp-rg"
  location = "West us 3"
}

#Add service plan
resource "azurerm_service_plan" "isaiah_plan" {
  name                = "isaiah-service-plan"
  resource_group_name = azurerm_resource_group.isaiah_rg.name
  location            = azurerm_resource_group.isaiah_rg.location
  sku_name            = "P1v2"
  os_type             = "Windows"
}

#Customize windows web app
resource "azurerm_windows_web_app" "isaiah_app" {
  name                = "isaiah-app-${random_string.suffix.result}"
  resource_group_name = azurerm_resource_group.isaiah_rg.name
  location            = azurerm_resource_group.isaiah_rg.location
  service_plan_id     = azurerm_service_plan.isaiah_plan.id

  site_config {
    always_on = true
  }

  app_settings = {
    "ENVIRONMENT" = "Production"
    "OWNER"       = "Isaiah"
    "WEBSITE_RUN_FROM_PACKAGE" = "1"
  }

  connection_string {
    name  = "Database"
    type  = "MySql"
    value = "Server=myserver.mysql.database.azure.com;Database=mydb;User Id=isaiah;Password=StrongPassword123;"
  }

  tags = {
    Owner       = "Isaiah"
    Environment = "Dev"
  }
}

# Create Resource Group
resource "azurerm_resource_group" "rg" {
  location = var.resource_group_location
  name     = "${var.prefix}-rg"
}

# Virtual Network
resource "azurerm_virtual_network" "vnet" {
  name                = "${var.prefix}-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

# Subnet
resource "azurerm_subnet" "subnet" {
  name                 = "${var.prefix}-subnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Public IP
resource "azurerm_public_ip" "public_ip" {
  name                = "${var.prefix}-public-ip"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

# Network Security Group
resource "azurerm_network_security_group" "nsg" {
  name                = "${var.prefix}-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  # RDP (You should replace with your public IP)
  security_rule {
    name                       = "Allow-RDP"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "3389"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  # HTTP
  security_rule {
    name                       = "Allow-HTTP"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Network Interface
resource "azurerm_network_interface" "nic" {
  name                = "${var.prefix}-nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.public_ip.id
  }
}

# Associate NSG
resource "azurerm_network_interface_security_group_association" "nsg_association" {
  network_interface_id      = azurerm_network_interface.nic.id
  network_security_group_id = azurerm_network_security_group.nsg.id
}

# Storage Account for Boot Diagnostics
resource "azurerm_storage_account" "diag" {
  name                     = "diag${random_id.rand.hex}"
  location                 = azurerm_resource_group.rg.location
  resource_group_name      = azurerm_resource_group.rg.name
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

# Windows Virtual Machine
resource "azurerm_windows_virtual_machine" "vm" {
  name                  = "${var.prefix}-vm"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.nic.id]
  size                  = "Standard_B1s"  # cheaper for lab

  admin_username = "isaiahadmin"
  admin_password = random_password.password.result

  os_disk {
    name                 = "${var.prefix}-osdisk"
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2022-datacenter-azure-edition"
    version   = "latest"
  }

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.diag.primary_blob_endpoint
  }
}

# Install IIS
resource "azurerm_virtual_machine_extension" "iis_install" {
  name                 = "iis-install"
  virtual_machine_id   = azurerm_windows_virtual_machine.vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.8"

  settings = &amp;lt;&amp;lt;SETTINGS
  {
    "commandToExecute": "powershell Install-WindowsFeature -Name Web-Server -IncludeManagementTools"
  }
  SETTINGS
}

# Random ID
resource "random_id" "rand" {
  byte_length = 4
}

# Random Password
resource "random_password" "password" {
  length  = 16
  special = true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: main.tf is the main infrastructure definition file.&lt;br&gt;
It contains the actual resources Terraform will create.&lt;br&gt;
Think of it as the core blueprint of your infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 5: Create Variable.tf file
&lt;/h2&gt;

&lt;p&gt;The main reason for creating variables.tf is for Azure VM. Before deploying a VM in main.tf in Terraform is important because it makes your infrastructure flexible, reusable, organized, and easier to maintain. Below is a clear explanation.&lt;/p&gt;

&lt;p&gt;If you create a VM directly in main.tf without variables, you will hard-code values like region, VM name, or size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "prefix" {
  description = "Prefix for all resources"
  default     = "isaiah"
}

variable "resource_group_location" {
  description = "Azure region"
  default     = "west US 3"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Initialize and Deploy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Initialize Terraform:&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;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Purpose&lt;/em&gt;&lt;br&gt;
Initializes the Terraform working directory.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why is it important&lt;/em&gt;&lt;br&gt;
This command prepares your project so Terraform can run properly.&lt;/p&gt;

&lt;p&gt;_What it does&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads providers (e.g., Azure, AWS, Google Cloud)&lt;/li&gt;
&lt;li&gt;Downloads modules&lt;/li&gt;
&lt;li&gt;Creates the .terraform folder&lt;/li&gt;
&lt;li&gt;Sets up the backend if configured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running terraform init downloads the AWS and Azure provider plugin. It prepares the environment before Terraform can run.&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%2Fm0uwofpa4mucr6bo6nnn.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%2Fm0uwofpa4mucr6bo6nnn.png" alt="terraform" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Validate Terraform:&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;terraform validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Purpose&lt;/em&gt;&lt;br&gt;
Checks if the Terraform configuration syntax is correct.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why it is important&lt;/em&gt;&lt;br&gt;
It helps detect errors in your code before deployment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What it checks&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax errors&lt;/li&gt;
&lt;li&gt;Missing brackets&lt;/li&gt;
&lt;li&gt;Incorrect variable references&lt;/li&gt;
&lt;li&gt;Invalid configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It checks if your code is written correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. terraform plan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Purpose&lt;/em&gt;&lt;br&gt;
Shows what Terraform will create, change, or delete before deployment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why it is important&lt;/em&gt;&lt;br&gt;
It allows you to preview the changes before applying them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What it shows&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources to be created&lt;/li&gt;
&lt;li&gt;Resources to be modified&lt;/li&gt;
&lt;li&gt;Resources to be destroyed&lt;/li&gt;
&lt;/ul&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%2F0h68qh59cdqkokf2ewj4.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%2F0h68qh59cdqkokf2ewj4.png" alt="terraform plan" width="800" height="347"&gt;&lt;/a&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%2Fjcuh4tmc2ufrnqf23l6e.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%2Fjcuh4tmc2ufrnqf23l6e.png" alt="terraform plan1" width="800" height="657"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 3 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means Terraform will create 12 new resources.&lt;/p&gt;

&lt;p&gt;Simple explanation&lt;/p&gt;

&lt;p&gt;👉 It shows the execution plan before making changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. terraform apply&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Purpose&lt;/em&gt;&lt;br&gt;
Executes the plan and creates the infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What it does&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploys resources to the cloud&lt;/li&gt;
&lt;li&gt;Creates VMs&lt;/li&gt;
&lt;li&gt;Creates networks&lt;/li&gt;
&lt;li&gt;Creates storage&lt;/li&gt;
&lt;li&gt;Updates infrastructure&lt;/li&gt;
&lt;/ul&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%2Fi5usb0jqplaqyzmpwjlp.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%2Fi5usb0jqplaqyzmpwjlp.png" alt="Terraform apply" width="800" height="395"&gt;&lt;/a&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%2Fe5qbbo8lomlv9j27ydm2.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%2Fe5qbbo8lomlv9j27ydm2.png" alt="Terraform Apply1" width="800" height="468"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple explanation&lt;br&gt;
👉 It actually builds the infrastructure.&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%2Fwrkrmy5uxpowiiw5k6vk.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%2Fwrkrmy5uxpowiiw5k6vk.png" alt="AWS resources" width="800" height="446"&gt;&lt;/a&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%2Fo1s075rz46rz3ww8o84s.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%2Fo1s075rz46rz3ww8o84s.png" alt="Azure resources" width="800" height="393"&gt;&lt;/a&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%2F1ib1ae7umpd0af5cl516.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%2F1ib1ae7umpd0af5cl516.png" alt="Azure1" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tree&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The main purpose of tree is to visualize how files and folders are organized inside a directory.&lt;/p&gt;

&lt;p&gt;Instead of listing files in a simple list like ls, tree shows the relationship between folders and subfolders.&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%2F0fay8kv73vpvg7j79haj.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%2F0fay8kv73vpvg7j79haj.png" alt="tree" width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 7 — Add Files to Git
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git add .
git commit -m "Initial commit: multi-cloud Terraform project"
git remote add origin https://github.com/izibili123/multi-cloud-terraform.git
git branch -M main
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Feeygwrhb3vogs6c5didk.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%2Feeygwrhb3vogs6c5didk.png" alt="git1" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 8 Terraform destroy
&lt;/h2&gt;

&lt;p&gt;In Terraform, the command terraform destroy is used to delete all the infrastructure resources that Terraform created.&lt;/p&gt;

&lt;p&gt;This is done to Prevent Unnecessary Cloud Costs&lt;/p&gt;

&lt;p&gt;Cloud resources keep running and continue charging money if not deleted.&lt;/p&gt;

&lt;p&gt;Using terraform destroy helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stop billing&lt;/li&gt;
&lt;li&gt;avoid unexpected cloud charges&lt;/li&gt;
&lt;li&gt;clean up test environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is very important when working with cloud providers&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&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%2Fvq74yxu2qzyjkze6zj8h.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%2Fvq74yxu2qzyjkze6zj8h.png" alt="terraform destroy" width="800" height="373"&gt;&lt;/a&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%2Frf7q1lmegywuw6dm2vy1.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%2Frf7q1lmegywuw6dm2vy1.png" alt="terraform2" width="800" height="440"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 0 to add, 0 to change, 22 to destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you must confirm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you really want to destroy all resources?
  Terraform will destroy all managed infrastructure.

Enter a value: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdy1sz50eddj68anrbemp.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%2Fdy1sz50eddj68anrbemp.png" alt="terraform destroy1" width="800" height="293"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 0 to add, 0 to change, 22 to destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Multi-cloud requires clear provider separation.&lt;/li&gt;
&lt;li&gt;State file protection is critical.&lt;/li&gt;
&lt;li&gt;Always destroy lab infrastructure.&lt;/li&gt;
&lt;li&gt;Azure and AWS networking models differ significantly.&lt;/li&gt;
&lt;li&gt;Infrastructure as Code improves reproducibility and scalability.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Multi-Cloud Matters
&lt;/h2&gt;

&lt;p&gt;Organizations use multi-cloud to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce vendor dependency&lt;/li&gt;
&lt;li&gt;Improve disaster recovery&lt;/li&gt;
&lt;li&gt;Optimize regional availability&lt;/li&gt;
&lt;li&gt;Compare cost efficiency between providers
Terraform makes multi-cloud deployment seamless.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates how Terraform can orchestrate infrastructure across AWS and Azure from a single configuration.&lt;/p&gt;

&lt;p&gt;By implementing EC2, RDS, and Azure VM resources, I built a resilient, scalable, and reproducible multi-cloud environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;br&gt;
Isaiah Izibili&lt;br&gt;
Cloud &amp;amp; DevOps Enthusiast&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
      <category>skillch</category>
    </item>
    <item>
      <title>CloudForge CI/CD Lab</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Mon, 12 Jan 2026 01:59:20 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/cloudforge-cicd-lab-gko</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/cloudforge-cicd-lab-gko</guid>
      <description>&lt;h2&gt;
  
  
  Building a Production-Grade CI/CD Pipeline with GitHub Actions, Docker &amp;amp; Kubernetes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern DevOps is not about tools alone — it’s about repeatable, automated, and reliable workflows that take code from a developer’s laptop all the way to production.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through CloudForge CI/CD Lab, a fully hands-on DevOps project that demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to build a real Node.js application&lt;/li&gt;
&lt;li&gt;How to test it properly&lt;/li&gt;
&lt;li&gt;How to containerize it securely with Docker&lt;/li&gt;
&lt;li&gt;How to automate everything using GitHub Actions&lt;/li&gt;
&lt;li&gt;How to deploy cleanly to Kubernetes using branch-based workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a toy project. Every step mirrors what real teams do in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites – Download These First!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estimated time: 15–30 minutes&lt;/p&gt;

&lt;p&gt;Before writing a single line of code, we need the right tools. DevOps workflows fail early if the environment isn’t consistent.&lt;/p&gt;

&lt;p&gt;✅ Required Tools&lt;br&gt;
1️⃣ Node.js (v18 or higher — LTS recommended)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;https://nodejs.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Choose LTS (v20.x as of 2025)&lt;/li&gt;
&lt;/ul&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%2Fj7cdjmadoil6p1iaxvqe.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%2Fj7cdjmadoil6p1iaxvqe.png" alt="Download Node.js" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node --version
npm --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F6es8cm2qe5uzll1qq71x.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%2F6es8cm2qe5uzll1qq71x.png" alt=" " width="800" height="378"&gt;&lt;/a&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%2Fze3a07y9fdf3b5b43hq3.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%2Fze3a07y9fdf3b5b43hq3.png" alt=" " width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2️⃣ Git (Latest Stable)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;https://git-scm.com/downloads&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Verify:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fbyxc8rijxlfkz6gbbz2a.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%2Fbyxc8rijxlfkz6gbbz2a.png" alt=" " width="800" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3️⃣ Docker Desktop&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;https://www.docker.com/products/docker-desktop/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install and start Docker Desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker --version
docker-compose --version

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

&lt;/div&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%2Fy9k4djjkxmu6eapfvvgc.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%2Fy9k4djjkxmu6eapfvvgc.png" alt=" " width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4️⃣ GitHub Account&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at: &lt;a href="https://github.com" rel="noopener noreferrer"&gt;https://github.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;This will host:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Your source code&lt;/li&gt;
&lt;li&gt;Your CI/CD pipeline&lt;/li&gt;
&lt;li&gt;Your container images (GHCR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5️⃣ Code Editor (Recommended)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code: &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;https://code.visualstudio.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔍 Verify Everything Is Installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node --version     # v18.x+ or v20.x+
npm --version      # 9.x+
git --version      # 2.34+
docker --version   # 24.x+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any command fails, fix it before proceeding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Set Up Git for Version Control&lt;/strong&gt;&lt;br&gt;
Why this matters&lt;/p&gt;

&lt;p&gt;Git needs to know who you are so commits are traceable. This is critical in team environments and CI pipelines.&lt;/p&gt;

&lt;p&gt;One-Time Git Configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

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

&lt;/div&gt;



&lt;p&gt;Create and Initialize the Project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir cloudforge-ci-cd-lab
cd cloudforge-ci-cd-lab
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have a clean Git repository ready for automation.&lt;/p&gt;

&lt;p&gt;Step 2: Build a Node.js Web Application&lt;/p&gt;

&lt;p&gt;Estimated time: 10–15 minutes&lt;/p&gt;

&lt;p&gt;This application is intentionally simple, but production-aware.&lt;/p&gt;

&lt;p&gt;Initialize the Node.js Project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a package.json file that manages dependencies and scripts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update package.json&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "cloudforge-ci-cd-lab",
  "version": "1.0.0",
  "description": "Production-grade DevOps CI/CD lab",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "test": "jest",
    "dev": "node app.js",
    "lint": "eslint ."
  },
  "keywords": ["devops", "nodejs", "docker", "kubernetes"],
  "author": "Your Name",
  "license": "MIT",
  "engines": {
    "node": "&amp;gt;=18.0.0"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "eslint": "^8.57.0",
    "supertest": "^7.1.4"
  }
}

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

&lt;/div&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%2F7sy94199b96uk3v8ikps.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%2F7sy94199b96uk3v8ikps.png" alt="Packagejason" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create app.js&lt;br&gt;
This server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposes health endpoints&lt;/li&gt;
&lt;li&gt;Emits Prometheus-style metrics&lt;/li&gt;
&lt;li&gt;Handles graceful shutdown&lt;/li&gt;
&lt;li&gt;Is Kubernetes-ready&lt;/li&gt;
&lt;li&gt;Creates an HTTP server that listens on port 3000&lt;/li&gt;
&lt;li&gt;Serves different endpoints (/, /health, /info, /metrics)&lt;/li&gt;
&lt;li&gt;Includes security headers and proper error handling&lt;/li&gt;
&lt;li&gt;Exports the server for testing
(Your full app.js code goes here exactly as you provided — unchanged)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Update app.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// core modules
const http = require("http");
const url = require("url");

// environment configuration
const PORT = process.env.PORT || 3000;
const ENVIRONMENT = process.env.NODE_ENV || "development";

let requestCount = 0;

// helper: send JSON responses
function sendJSON(res, statusCode, data) {
  res.statusCode = statusCode;
  res.setHeader("Content-Type", "application/json");
  res.end(JSON.stringify(data, null, 2));
}

// helper: send HTML responses
function sendHTML(res, statusCode, content) {
  res.statusCode = statusCode;
  res.setHeader("Content-Type", "text/html");
  res.end(content);
}

// helper: send Prometheus metrics
function sendMetrics(res) {
  const mem = process.memoryUsage();
  const metrics = `
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total ${requestCount}

# HELP app_uptime_seconds Application uptime in seconds
# TYPE app_uptime_seconds gauge
app_uptime_seconds ${process.uptime()}

# HELP nodejs_memory_usage_bytes Node.js memory usage
# TYPE nodejs_memory_usage_bytes gauge
nodejs_memory_usage_bytes{type="rss"} ${mem.rss}
nodejs_memory_usage_bytes{type="heapUsed"} ${mem.heapUsed}
nodejs_memory_usage_bytes{type="heapTotal"} ${mem.heapTotal}
nodejs_memory_usage_bytes{type="external"} ${mem.external}
`;
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end(metrics);
}

// main server
const server = http.createServer((req, res) =&amp;gt; {
  requestCount++;
  const timestamp = new Date().toISOString();
  const { pathname } = url.parse(req.url, true);

  // logging
  console.log(
    `${timestamp} - ${req.method} ${pathname} - ${
      req.headers["user-agent"] || "Unknown"
    }`
  );

  // CORS headers
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");

  // security headers
  res.setHeader("X-Content-Type-Options", "nosniff");
  res.setHeader("X-Frame-Options", "DENY");
  res.setHeader("X-XSS-Protection", "1; mode=block");

  // route handling
  switch (pathname) {
    case "/":
      sendHTML(
        res,
        200,
        `
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;DevOps Lab 2025&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
    .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; }
    .endpoint { background: #f8f9fa; padding: 15px; margin: 10px 0; border-radius: 5px; border-left: 4px solid #007bff; }
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div class="header"&amp;gt;
    &amp;lt;h1&amp;gt;DevOps Lab 2025&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Modern Node.js application with CI/CD pipeline&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;h2&amp;gt;Available Endpoints:&amp;lt;/h2&amp;gt;
  &amp;lt;div class="endpoint"&amp;gt;&amp;lt;strong&amp;gt;GET /&amp;lt;/strong&amp;gt; - This welcome page&amp;lt;/div&amp;gt;
  &amp;lt;div class="endpoint"&amp;gt;&amp;lt;strong&amp;gt;GET /health&amp;lt;/strong&amp;gt; - Health check (JSON)&amp;lt;/div&amp;gt;
  &amp;lt;div class="endpoint"&amp;gt;&amp;lt;strong&amp;gt;GET /info&amp;lt;/strong&amp;gt; - System information&amp;lt;/div&amp;gt;
  &amp;lt;div class="endpoint"&amp;gt;&amp;lt;strong&amp;gt;GET /metrics&amp;lt;/strong&amp;gt; - Prometheus metrics&amp;lt;/div&amp;gt;
  &amp;lt;p&amp;gt;Environment: &amp;lt;strong&amp;gt;${ENVIRONMENT}&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Server time: &amp;lt;strong&amp;gt;${timestamp}&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Requests served: &amp;lt;strong&amp;gt;${requestCount}&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;`
      );
      break;

    case "/health":
      sendJSON(res, 200, {
        status: "healthy",
        timestamp,
        uptime: process.uptime(),
        environment: ENVIRONMENT,
        version: "1.0.0",
        node_version: process.version,
        requests_served: requestCount,
      });
      break;

    case "/info":
      sendJSON(res, 200, {
        platform: process.platform,
        architecture: process.arch,
        node_version: process.version,
        memory_usage: process.memoryUsage(),
        environment: ENVIRONMENT,
        pid: process.pid,
        uptime: process.uptime(),
      });
      break;

    case "/metrics":
      sendMetrics(res);
      break;

    default:
      sendJSON(res, 404, {
        error: "Not Found",
        message: `Route ${pathname} not found`,
        timestamp,
      });
  }
});

// graceful shutdown
function shutdown(signal) {
  console.log(`\nReceived ${signal}, shutting down gracefully...`);
  server.close(() =&amp;gt; {
    console.log("Server closed");
    process.exit(0);
  });
}
process.on("SIGTERM", () =&amp;gt; shutdown("SIGTERM"));
process.on("SIGINT", () =&amp;gt; shutdown("SIGINT"));

// start server
server.listen(PORT, () =&amp;gt; {
  console.log(`🚀 Server running at http://localhost:${PORT}/`);
  console.log(`Environment: ${ENVIRONMENT}`);
  console.log(`Node.js version: ${process.version}`);
});

// export for testing
module.exports = server;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fl391zt9esfyxtqipw3jm.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%2Fl391zt9esfyxtqipw3jm.png" alt="appupdate" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev jest eslint supertest
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll now see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;node_modules/&lt;/li&gt;
&lt;li&gt;package-lock.json&lt;/li&gt;
&lt;/ul&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%2Fy6pbdh0736onk8j7uabf.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%2Fy6pbdh0736onk8j7uabf.png" alt="npm install save" width="800" height="304"&gt;&lt;/a&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%2Fp4xzym37hujwb64f0xif.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%2Fp4xzym37hujwb64f0xif.png" alt="npm install" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create Proper Automated Tests
&lt;/h2&gt;

&lt;p&gt;Estimated time: 10 minutes&lt;br&gt;
Testing is mandatory in CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;Create Test Directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir tests
touch tests/app.test.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add Tests&lt;br&gt;
(Copy this code into tests/app.test.js exactly as provided)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const request = require('supertest');
const server = require('../app');

describe('App Endpoints', () =&amp;gt; {
  afterAll(() =&amp;gt; {
    server.close();
  });

  test('GET / should return welcome page', async () =&amp;gt; {
    const response = await request(server).get('/');
    expect(response.status).toBe(200);
    expect(response.text).toContain('DevOps Lab 2025');
  });

  test('GET /health should return health status', async () =&amp;gt; {
    const response = await request(server).get('/health');
    expect(response.status).toBe(200);
    expect(response.body.status).toBe('healthy');
    expect(response.body.timestamp).toBeDefined();
    expect(typeof response.body.uptime).toBe('number');
  });

  test('GET /info should return system info', async () =&amp;gt; {
    const response = await request(server).get('/info');
    expect(response.status).toBe(200);
    expect(response.body.platform).toBeDefined();
    expect(response.body.node_version).toBeDefined();
  });

  test('GET /metrics should return prometheus metrics', async () =&amp;gt; {
    const response = await request(server).get('/metrics');
    expect(response.status).toBe(200);
    expect(response.text).toContain('http_requests_total');
    expect(response.text).toContain('app_uptime_seconds');
  });

  test('GET /nonexistent should return 404', async () =&amp;gt; {
    const response = await request(server).get('/nonexistent');
    expect(response.status).toBe(404);
    expect(response.body.error).toBe('Not Found');
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F9qcdt4h2o33vlg93su18.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%2F9qcdt4h2o33vlg93su18.png" alt="testapp" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Jest configuration&lt;/strong&gt;&lt;br&gt;
Create jest.config.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  testEnvironment: 'node',
  collectCoverage: true,
  coverageDirectory: 'coverage',
  testMatch: ['**/tests/**/*.test.js'],
  verbose: true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F6hv77n9dacdp495led2t.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%2F6hv77n9dacdp495led2t.png" alt="Jest app" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: GitHub Actions CI/CD Pipeline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estimated time: 15 minutes&lt;/p&gt;

&lt;p&gt;This pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests on multiple Node versions&lt;/li&gt;
&lt;li&gt;Builds multi-arch Docker images&lt;/li&gt;
&lt;li&gt;Scans for vulnerabilities&lt;/li&gt;
&lt;li&gt;Pushes to GitHub Container Registry&lt;/li&gt;
&lt;li&gt;Supports staging &amp;amp; production deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Create Workflow Directory&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;mkdir -p .github/workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create CI/CD pipeline file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.github/workflows/ci.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Use your full CI workflow YAML exactly as provided)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
    tags: [ 'v*' ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    name: Test &amp;amp; Lint
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [20, 22]

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linting
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Security audit
        run: npm audit --audit-level=critical || echo "Audit completed with warnings"

  build:
    name: Build &amp;amp; Push Image
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == 'push'

    permissions:
      contents: read
      packages: write
      security-events: write

    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}
      image-digest: ${{ steps.build.outputs.digest }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          platforms: linux/amd64,linux/arm64

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix={{branch}}-
            type=raw,value=${{ github.run_id }}
            type=raw,value=latest,enable={{is_default_branch}}
          labels: |
            org.opencontainers.image.title=DevOps Lab 2025
            org.opencontainers.image.description=Modern Node.js DevOps application

      - name: Build and push Docker image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          target: production

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@0.24.0
        with:
          image-ref: ${{ steps.meta.outputs.tags }}
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
        continue-on-error: true

      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v3
        if: always() &amp;amp;&amp;amp; hashFiles('trivy-results.sarif') != ''
        with:
          sarif_file: 'trivy-results.sarif'

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/develop'
    environment: staging

    steps:
      - name: Deploy to Staging
        run: |
          echo "🚀 Deploying to staging environment..."
          echo "Image: ${{ needs.build.outputs.image-tag }}"
          echo "Digest: ${{ needs.build.outputs.image-digest }}"
          # Add your staging deployment commands here (kubectl, helm, etc.)

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    environment: production

    steps:
      - name: Deploy to Production
        run: |
          echo "🎯 Deploying to production environment..."
          echo "Image: ${{ needs.build.outputs.image-tag }}"
          echo "Digest: ${{ needs.build.outputs.image-digest }}"
          # Add your production deployment commands here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline demonstrates real-world CI/CD maturity, not demo-level automation.&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%2F29o97juudx4ldumew8dg.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%2F29o97juudx4ldumew8dg.png" alt="Git CICD" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Dockerfile (Production-Grade)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estimated time: 5 minutes&lt;/p&gt;

&lt;p&gt;This Dockerfile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses multi-stage builds for smaller image size&lt;/li&gt;
&lt;li&gt;Installs curl for health checks&lt;/li&gt;
&lt;li&gt;Creates a non-root user for security&lt;/li&gt;
&lt;li&gt;Sets up proper file permissions&lt;/li&gt;
&lt;li&gt;Configures health checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Use your full Dockerfile exactly as provided)&lt;/p&gt;

&lt;p&gt;Create Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Multi-stage build for optimized image
FROM node:20-alpine AS dependencies

# Update packages for security
RUN apk update &amp;amp;&amp;amp; apk upgrade --no-cache

WORKDIR /app

# Copy package files first for better caching
COPY package*.json ./

# Install only production dependencies
RUN npm ci --only=production &amp;amp;&amp;amp; npm cache clean --force

# Production stage  
FROM node:20-alpine AS production

# Update packages and install necessary tools
RUN apk update &amp;amp;&amp;amp; apk upgrade --no-cache &amp;amp;&amp;amp; \
    apk add --no-cache curl dumb-init &amp;amp;&amp;amp; \
    rm -rf /var/cache/apk/*

# Create non-root user with proper permissions
RUN addgroup -g 1001 -S nodejs &amp;amp;&amp;amp; \
    adduser -S nodeuser -u 1001 -G nodejs

WORKDIR /app

# Copy dependencies from previous stage with proper ownership
COPY --from=dependencies --chown=nodeuser:nodejs /app/node_modules ./node_modules

# Copy application code with proper ownership
COPY --chown=nodeuser:nodejs package*.json ./
COPY --chown=nodeuser:nodejs app.js ./

# Switch to non-root user
USER nodeuser

# Expose port
EXPOSE 3000

# Health check with proper timing for Node.js startup
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# Use dumb-init for proper signal handling in containers
ENTRYPOINT ["dumb-init", "--"]

# Start application
CMD ["npm", "start"]

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

&lt;/div&gt;



&lt;p&gt;(Use your full Dockerfile exactly as provided)&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%2F522y3ne3vbf9ituf6l57.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%2F522y3ne3vbf9ituf6l57.png" alt="Dockerfile" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Essential Configuration Files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estimated time: 5 minutes&lt;br&gt;
What this step does: Creates configuration files that tell various tools what to ignore, how to behave, and what settings to use.&lt;/p&gt;

&lt;p&gt;These files keep your repo clean and secure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.dockerignore&lt;/li&gt;
&lt;li&gt;.gitignore&lt;/li&gt;
&lt;li&gt;.env.example&lt;/li&gt;
&lt;li&gt;.eslintrc.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Use your provided configurations verbatim)&lt;/p&gt;

&lt;p&gt;Create .dockerignore&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Dependencies
node_modules
npm-debug.log*

# Git &amp;amp; GitHub
.git
.github

# Environment files
.env
.env.local
.env.*.local

# Logs
logs
*.log

# Coverage &amp;amp; test output
coverage
.nyc_output

# Editor/IDE configs
.vscode
.idea
*.swp
*.swo

# OS-specific files
.DS_Store
Thumbs.db

# Project files you don’t want in the image
README.md
tests/
jest.config.js
.eslintrc

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

&lt;/div&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%2Fq2fzq4mjropnyaauoq6b.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%2Fq2fzq4mjropnyaauoq6b.png" alt="dockerignor" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this arrangement works&lt;/strong&gt;&lt;br&gt;
Grouped logically (dependencies, VCS, env files, logs, coverage, editor configs, OS junk, project files).&lt;/p&gt;

&lt;p&gt;Each entry on its own line → Docker will correctly ignore them when building images.&lt;/p&gt;

&lt;p&gt;Comments (# ...) → optional, but they make the file easier to read and maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create .gitignore&lt;/strong&gt;&lt;br&gt;
Create .gitignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ===============================
# Dependencies
# ===============================
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# ===============================
# Runtime Data
# ===============================
pids
*.pid
*.seed
*.pid.lock

# ===============================
# Coverage &amp;amp; Test Reports
# ===============================
coverage/
.nyc_output/

# ===============================
# Environment Variables
# ===============================
.env
.env.local
.env.*.local

# ===============================
# Logs
# ===============================
logs/
*.log

# ===============================
# IDE / Editor
# ===============================
.vscode/
.idea/
*.swp
*.swo

# ===============================
# OS Files
# ===============================
.DS_Store
Thumbs.db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjita6kmsun4wpxg2pd01.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%2Fjita6kmsun4wpxg2pd01.png" alt="gitignor" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create environment template&lt;/strong&gt;&lt;br&gt;
Create .env.example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ===============================
# Server Configuration
# ===============================
PORT=3000
NODE_ENV=production

# ===============================
# Logging Configuration
# ===============================
LOG_LEVEL=info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fxfkkkq3ijffyeajzddjp.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%2Fxfkkkq3ijffyeajzddjp.png" alt="envverables" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create ESLint configuration&lt;/strong&gt;&lt;br&gt;
Create .eslintrc.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  env: {
    node: true,
    es2021: true,
    jest: true
  },
  extends: ['eslint:recommended'],
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module'
  },
  rules: {
    'no-console': 'off',
    'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }]
  }
};

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

&lt;/div&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%2Fg9duk208oelfd4fm10yx.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%2Fg9duk208oelfd4fm10yx.png" alt="ensincfile" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Docker Compose for Development&lt;/strong&gt;&lt;br&gt;
Time Required: 5 minutes&lt;/p&gt;

&lt;p&gt;What this step does: Creates a Docker Compose file that makes it easy to run your application and any supporting services with a single command.&lt;/p&gt;

&lt;p&gt;Create docker-compose.yml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - PORT=3000
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fz5g49dnfqjbq4cpo7aev.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%2Fz5g49dnfqjbq4cpo7aev.png" alt="docker compose" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8: Test Everything Locally&lt;/strong&gt;&lt;br&gt;
Time Required: 10 minutes&lt;/p&gt;

&lt;p&gt;What this step does: Shows you how to actually run and test your application locally before deploying it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install and Test Locally&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;# Install all dependencies from package.json
npm install

# Run your test suite to make sure everything works
npm test

# Start the application server
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you'll see:&lt;/p&gt;

&lt;p&gt;Tests should pass with green checkmarks: ✓ GET / should return welcome page&lt;br&gt;
Server starts and shows: 🚀 Server running at &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&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%2Fvshijbv3h63n0h8att89.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%2Fvshijbv3h63n0h8att89.png" alt="npminstall" width="800" height="241"&gt;&lt;/a&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%2Feftqzw5codsmjlp42269.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%2Feftqzw5codsmjlp42269.png" alt="npmtest1" width="800" height="395"&gt;&lt;/a&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%2Fyg7zuuyx08x5l0i3oqe9.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%2Fyg7zuuyx08x5l0i3oqe9.png" alt="npmstart" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Endpoints&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;curl http://localhost:3000/
curl http://localhost:3000/health
curl http://localhost:3000/info
curl http://localhost:3000/metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Homepage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;_Purpose: Tests that your application is serving its main route (/).&lt;/p&gt;

&lt;p&gt;Why it matters:_&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirms the server is running and listening on port 3000.&lt;/li&gt;
&lt;li&gt;Ensures your app can respond to basic HTTP requests.&lt;/li&gt;
&lt;li&gt;This is often the first check to verify deployment success.&lt;/li&gt;
&lt;/ul&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%2F083tfbv16wgf54ygg0vt.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%2F083tfbv16wgf54ygg0vt.png" alt="Localhost" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Health check JSON&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Purpose: Calls the /health endpoint, which usually returns a simple JSON like:&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health checks are critical for monitoring and orchestration tools (Docker, Kubernetes, CI/CD pipelines).&lt;/li&gt;
&lt;li&gt;They provide a lightweight way to confirm the app is alive without loading the full homepage.&lt;/li&gt;
&lt;li&gt;Used by load balancers and cloud platforms to decide if traffic should be routed to this instance.&lt;/li&gt;
&lt;/ul&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%2Fzc36s2r00o7br7f06dha.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%2Fzc36s2r00o7br7f06dha.png" alt="Health check" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** System info JSON  **&lt;br&gt;
&lt;em&gt;Purpose: Retrieves metadata about the system or application (version, environment, uptime, etc.).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why it matters:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Helps developers and operators quickly see runtime details.&lt;/li&gt;
&lt;li&gt;Useful for debugging and confirming the app is running with the expected configuration.&lt;/li&gt;
&lt;li&gt;Can expose build info (commit hash, build date) for CI/CD traceability.&lt;/li&gt;
&lt;/ul&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%2Fy7qpdegomk0fq22431kl.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%2Fy7qpdegomk0fq22431kl.png" alt="system info" width="800" height="715"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prometheus metrics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Purpose: Exposes application metrics in a format Prometheus can scrape (e.g., request counts, latency, memory usage).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enables observability: monitoring performance, resource usage, and reliability.&lt;/li&gt;
&lt;li&gt;Critical for production systems where you need dashboards (Grafana) and alerts.&lt;/li&gt;
&lt;li&gt;Lets you track trends over time and detect anomalies (e.g., rising error rates).&lt;/li&gt;
&lt;/ul&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%2Fw8nm7j8tyqkoell6f2hy.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%2Fw8nm7j8tyqkoell6f2hy.png" alt="metrics" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why These Steps Together Are Important&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;They form a complete validation suite:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/ → confirms the app is serving content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/health → confirms the app is alive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/info → confirms the app is running with the right config.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/metrics → confirms the app is observable and ready for monitoring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This combination is standard in DevOps and CI/CD pipelines to ensure deployments are healthy before traffic is routed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Docker Testing
&lt;/h2&gt;

&lt;p&gt;These commands form a simple, reliable workflow to build, run, verify, and clean up your application as a container. In CI/CD, they help ensure every change can be packaged consistently, tested predictably, and deployed with confidence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build image
docker build -t my-devops-app:latest .

# Run container
docker run -d \
  --name my-devops-container \
  -p 3000:3000 \
  --restart unless-stopped \
  my-devops-app:latest

# Check container status
docker ps
docker logs my-devops-container

# Test health check
curl http://localhost:3000/health

# Stop container
docker stop my-devops-container
docker rm my-devops-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Build Image
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t my-devops-app:latest .

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

&lt;/div&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%2Fmj65a27btfvh317wcpha.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%2Fmj65a27btfvh317wcpha.png" alt="docker build" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What it does:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads the Dockerfile in the current directory (.).&lt;/li&gt;
&lt;li&gt;Builds a container image containing your app and its dependencies.&lt;/li&gt;
&lt;li&gt;Tags the image as my-devops-app:latest for easy reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Why it’s important in CI/CD:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistency: Every build produces the same image, eliminating “works on my machine” issues.&lt;/li&gt;
&lt;li&gt;Portability: The image can be deployed across environments (dev, staging, prod).&lt;/li&gt;
&lt;li&gt;Versioning: Tags (latest, commit SHA, release numbers) allow tracking and rollback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Run container&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;    docker run -d \
  --name my-devops-container \
  -p 3000:3000 \
  --restart unless-stopped \
  my-devops-app:latest

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

&lt;/div&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%2Fkexlmjrg1ry3mf103g2x.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%2Fkexlmjrg1ry3mf103g2x.png" alt="docker run" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. What it does:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;-d: Runs the container in detached mode so the process continues in the background.&lt;/li&gt;
&lt;li&gt;--name my-devops-container: Assigns a stable name for easier management and log retrieval.&lt;/li&gt;
&lt;li&gt;-p 3000:3000: Publishes container port 3000 to host port 3000, making the app reachable at localhost:3000.&lt;/li&gt;
&lt;li&gt;--restart unless-stopped: Restarts the container automatically after failures or host reboots unless you explicitly stop it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;2. Why it matters in CI/CD:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integration testing: Spins up a production‑like instance to run tests against real endpoints.&lt;/li&gt;
&lt;li&gt;Environment parity: Mirrors how the app will run in production, catching config and runtime issues early.&lt;/li&gt;
&lt;li&gt;Resilience during validation: Restart policies reduce flakiness in ephemeral CI environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Check container status&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;docker ps
docker logs my-devops-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fr4c4ofp3fiv2z0y5weyc.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%2Fr4c4ofp3fiv2z0y5weyc.png" alt="docker container" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What they do:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker ps: Lists running containers—quick confirmation that your app started successfully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker logs my-devops-container: Streams stdout/stderr from the container for diagnostics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it matters in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fast feedback: Detects startup failures (crashes, port conflicts, missing env vars) before tests run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Actionable debugging: Logs reveal misconfigurations, dependency errors, or health probe failures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated gates: Pipelines can parse logs or check docker ps to decide whether to proceed or fail early.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Test health check&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;curl http://localhost:3000/health

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What it does:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls the app’s liveness/readiness endpoint, typically returning 200 OK with a simple JSON payload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it matters in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Readiness assurance: Confirms the service is not only running but ready to serve traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment safety: Prevents promoting builds that start but aren’t healthy (e.g., DB not connected, migrations pending).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated validation: Pipelines can assert status codes and response bodies to enforce health standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Stop and remove container&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;docker stop my-devops-container
docker rm my-devops-container

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

&lt;/div&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%2Fl0vz9fafvorp1eyzvu2u.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%2Fl0vz9fafvorp1eyzvu2u.png" alt="docker stop" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What they do:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker stop: Sends a graceful shutdown signal (SIGTERM) to the containerized process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;docker rm: Deletes the stopped container’s resources and metadata (the image remains int&lt;br&gt;
act).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it matters in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean slate: Avoids port conflicts, stale state, and resource leaks between pipeline runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource hygiene: Frees CPU/memory on runners, keeping builds stable and predictable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determinism: Ensures each run starts from a known baseline, improving the reliability of test results.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker Compose Commands
&lt;/h2&gt;

&lt;p&gt;These three docker-compose commands represent the full lifecycle of multi‑container applications in a DevOps CI/CD pipeline. Let’s break them down carefully:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Start all services&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What it does:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reads the docker-compose.yml file in your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;Starts all services defined there (e.g., app, database, cache, message broker).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;-d runs them in detached mode, so they run in the background.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it’s important in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi‑service orchestration: Many apps depend on multiple components (e.g., Node.js  + MongoDB + Redis). This command spins them all up together.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistency: Ensures every developer, tester, and pipeline runner uses the same service definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automation: Pipelines can bring up the full stack before running integration tests, mimicking production.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;2. View real‑time logs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose logs -f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjcqw0rlmekewa045576n.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%2Fjcqw0rlmekewa045576n.png" alt="docker compose log" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What it does:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Streams logs from all running services defined in docker-compose.yml.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;-f means follow mode, so you see logs in real time as they’re generated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it’s important in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observability: Lets you monitor startup progress and catch errors (e.g., DB connection failures, missing env vars).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debugging: If a pipeline fails, logs show exactly which service broke.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validation: Confirms services are running correctly before tests proceed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;3. Stop and clean up&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F13f99csvss2q0wmz5wbi.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%2F13f99csvss2q0wmz5wbi.png" alt="docker compose down" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What it does:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stops all running services defined in docker-compose.yml.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removes containers, networks, and temporary volumes created by docker-compose up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leaves images intact (so you don’t have to rebuild next time).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it’s important in CI/CD:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean environments: Prevents leftover containers or networks from interfering with future runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource hygiene: Frees CPU, memory, and disk space on build agents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeatability: Ensures every pipeline run starts fresh, avoiding state leakage between builds.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 9: Push to GitHub&lt;/strong&gt;&lt;br&gt;
Estimated time: 10 minutes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stages all the changes in your project directory (the . means “everything here”). It tells Git which files you want to include in the next commit.&lt;br&gt;
Why it’s important: Without staging, Git won’t know which files to save. This step ensures your project files (code, configs, Dockerfiles, workflows) are prepared to be recorded in history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "Initial commit: Complete CloudForge CI/CD Lab"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a snapshot of your staged files with a descriptive message. The commit becomes a permanent record in your repository’s history.&lt;br&gt;
Why it’s important: Commits are the foundation of version control. They let you track changes, roll back if needed, and provide context for what was done. The message “Initial commit” marks the starting point of your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git branch -M main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This renames your current branch to main. GitHub uses main as the default branch for new repositories.&lt;br&gt;
Why it’s important: Aligning with GitHub’s default branch ensures consistency. Your CI/CD workflows are often configured to run on main, so this step guarantees your pipeline will trigger correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add origin https://github.com/YOUR_USERNAME/cloudforge-ci-cd-lab.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This links your local repository to a remote repository hosted on GitHub. The name origin is a shorthand reference to that remote.&lt;br&gt;
Why it’s important: Without a remote, your code only exists locally. Adding GitHub as the remote allows you to push your project online, collaborate with others, and integrate with GitHub Actions for CI/CD.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pushes your local main branch commits to the remote repository on GitHub. The -u flag sets origin/main as the default upstream branch, so future pushes and pulls are simpler.&lt;br&gt;
Why it’s important: This is the moment your code leaves your machine and enters GitHub. Once it’s there, GitHub Actions detects the workflow file (.github/workflows/ci.yml) and automatically starts your CI/CD pipeline.&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%2Fnqroxf3oxtsc4fnepypb.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%2Fnqroxf3oxtsc4fnepypb.png" alt="Git workflow" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The CI/CD pipeline now runs automatically&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because you’ve pushed the workflow file to GitHub, every new commit or pull request to main (or other configured branches like develop) will trigger the pipeline. GitHub Actions will build, test, and validate your project without manual intervention.&lt;br&gt;
Why it’s important: This automation ensures that every change is tested and verified before deployment, reducing errors and speeding up delivery. It’s the essence of DevOps — continuous integration and continuous delivery.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 10: Kubernetes Deployment Configurations
&lt;/h2&gt;

&lt;p&gt;These steps define how your app should run in two environments—staging and production—using Kubernetes manifests. These files describe the desired state (replicas, images, ports, health checks, resources), and Kubernetes continuously enforces that state. In a CI/CD pipeline, your builds produce container images, and these manifests tell Kubernetes which image to run, how many copies, and how to expose and monitor them—so deployments become repeatable, observable, and safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory structure and environment separation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Purpose:&lt;br&gt;&lt;br&gt;
You create k8s/staging and k8s/production to keep environment-specific configs isolated. This prevents accidental cross-environment changes and makes promotion clear—staging uses one set of manifests, production another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why it matters in CI/CD: &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clear promotion paths: CI builds and tags images (e.g., develop-latest for staging, latest for production), then CD applies the corresponding manifests. Risk control: Staging can have fewer replicas, looser resource limits, or different probes, while production is stricter and scaled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p k8s/staging k8s/production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Staging deployment: intent and key fields&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create k8s/staging/deployment.yml&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%2F4x50ycww1b4cyu18b0z4.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%2F4x50ycww1b4cyu18b0z4.png" alt="staging code k8s" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste the following command into the just-created file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: devops-app-staging
  namespace: staging
spec:
  replicas: 2
  selector:
    matchLabels:
      app: devops-app
      environment: staging
  template:
    metadata:
      labels:
        app: devops-app
        environment: staging
    spec:
      containers:
      - name: app
        image: ghcr.io/YOUR_GITHUB_USERNAME/my-devops-project:develop-latest
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "staging"
        - name: PORT
          value: "3000"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: devops-app-service-staging
  namespace: staging
spec:
  selector:
    app: devops-app
    environment: staging
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: LoadBalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F3oahun8in1m0swjoasuq.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%2F3oahun8in1m0swjoasuq.png" alt="Staging area" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why it matters in CI/CD: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Safe validation: Staging runs the latest develop image with health checks, so your pipeline can deploy, verify readiness, run tests, and catch issues before production. Observability: Probes provide automated signals to fail fast if the app isn’t healthy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production deployment: scaling, resources, and stricter controls&lt;/strong&gt;&lt;br&gt;
Create Production Deployment&lt;/p&gt;

&lt;p&gt;Create: touch k8s/production/deployment.yml:&lt;/p&gt;

&lt;p&gt;copy the commands into the just-created file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: devops-app-production
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: devops-app
      environment: production
  template:
    metadata:
      labels:
        app: devops-app
        environment: production
    spec:
      containers:
      - name: app
        image: ghcr.io/YOUR_GITHUB_USERNAME/my-devops-project:latest
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        - name: PORT
          value: "3000"
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: devops-app-service-production
  namespace: production
spec:
  selector:
    app: devops-app
    environment: production
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: LoadBalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0tdvvwjda8e148yil7wt.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%2F0tdvvwjda8e148yil7wt.png" alt="Production" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why it matters in CI/CD:
Reliability and cost control: Resource requests/limits prevent overconsumption and stabilize workloads. Zero-downtime readiness: Readiness probes ensure new pods receive traffic only when ready, enabling safe rolling updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Image tags and CI/CD flow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Develop vs. latest:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Staging uses: develop-latest—built from the develop branch on each push.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Production uses: latest—built from main or tagged releases after passing tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pipeline fit:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CI: Builds and pushes images to GHCR with branch-specific tags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CD (staging): Applies k8s/staging/deployment.yml after CI succeeds, validates via probes/tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CD (production): Applies k8s/production/deployment.yml upon approval or automated promotion, leveraging readiness for safe rollout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 11: Complete Deployment Workflow
&lt;/h2&gt;

&lt;p&gt;This final step ties together everything you’ve built in your CI/CD pipeline by introducing a branch‑based deployment strategy. The idea is simple but powerful: each branch in your Git repository corresponds to a specific environment. The develop branch is used for staging, so whenever you push changes there, GitHub Actions automatically runs tests and deploys the latest build to the staging cluster. This allows you to validate new features in a safe, production‑like environment without affecting real users.&lt;/p&gt;

&lt;p&gt;The main branch is reserved for production, meaning only code that has been tested and approved gets merged into it. Once you push to main, GitHub Actions executes the full pipeline again, but this time it deploys to your production environment, ensuring that only stable builds reach end users. Pull requests are handled differently: they trigger tests but do not deploy, which provides a safeguard by catching issues before merging into staging or production.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Deploy to staging:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create and switch to develop branch
git checkout -b develop

# Make your changes, then commit and push
git add .
git commit -m "Add new feature"
git push origin develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5i8fwhiyu3xt0p2zh2wh.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%2F5i8fwhiyu3xt0p2zh2wh.png" alt="git staging K8s" width="800" height="296"&gt;&lt;/a&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%2Fi7qojwqr8pzm899t6oe7.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%2Fi7qojwqr8pzm899t6oe7.png" alt="git push" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Deploy to production:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switch to main branch
git checkout main

# Merge changes from develop
git merge develop

# Push to trigger production deployment
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitor Deployments
&lt;/h2&gt;

&lt;p&gt;After deployment, monitoring is critical. GitHub Actions provides real‑time visibility into pipeline runs, while the GitHub Container Registry stores your built images for traceability. Finally, health checks against your staging and production URLs confirm that the applications are live and responding correctly. This workflow enforces discipline, reduces risk, and ensures that every change follows a predictable path from development to production.&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%2Fead8hh5mm62odp5gh4ul.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%2Fead8hh5mm62odp5gh4ul.png" alt="staging Action" width="800" height="296"&gt;&lt;/a&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%2F1hhonustgrynbxvodk0k.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%2F1hhonustgrynbxvodk0k.png" alt="push to production" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: What CloudForge CI/CD Lab Really Teaches
&lt;/h2&gt;

&lt;p&gt;CloudForge CI/CD Lab is not about learning individual tools — it is about understanding systems thinking in modern software delivery.&lt;/p&gt;

&lt;p&gt;By building this pipeline from first principles, we moved deliberately through every layer of a real production workflow: version control discipline, application design for operability, automated testing, containerization, continuous integration, and declarative deployment. Each step was introduced not because it is fashionable, but because it solves a concrete problem that teams face in real-world environments.&lt;/p&gt;

&lt;p&gt;More importantly, this project demonstrates a shift-left mindset. Problems are detected early through editor annotations, linting, and automated tests — long before they reach CI pipelines or production clusters. This is how high-performing teams reduce failures, shorten feedback loops, and ship confidently.&lt;/p&gt;

&lt;p&gt;CloudForge CI/CD Lab also highlights that production readiness is not a single feature, but the accumulation of many small, intentional decisions: running containers as non-root, handling graceful shutdowns, enforcing resource limits, and treating infrastructure as code. None of these choices are optional in serious systems, and together they form the foundation of reliable delivery.&lt;/p&gt;

&lt;p&gt;If you can build, explain, and reason about a pipeline like this, you are no longer just “using DevOps tools.” You are thinking like a DevOps engineer — one who understands why automation exists, how systems fail, and how to design workflows that scale with both code and teams.&lt;/p&gt;

&lt;p&gt;This lab is not the end of the journey, but it is a solid, production-aligned starting point. From here, the same principles extend naturally into cloud platforms, advanced observability, progressive delivery, and platform engineering — without changing the fun&lt;/p&gt;

</description>
      <category>skilch</category>
      <category>devops</category>
      <category>webdev</category>
      <category>containers</category>
    </item>
    <item>
      <title>Complete Guide to Kubernetes Flavors, Their Categories &amp; How to Install Minikube on Linux (with Docker Driver)</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sat, 06 Dec 2025 11:39:27 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/complete-guide-to-kubernetes-flavors-their-categories-how-to-install-minikube-on-linux-with-4cfj</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/complete-guide-to-kubernetes-flavors-their-categories-how-to-install-minikube-on-linux-with-4cfj</guid>
      <description>&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;

&lt;p&gt;Kubernetes has grown into the most powerful container orchestration system in the world, but it does not exist as a single product. Instead, it exists in multiple flavors, each tailored for different use cases such as enterprise production, hybrid cloud, edge, research, or local development.&lt;/p&gt;

&lt;p&gt;This article breaks down the Kubernetes ecosystem into understandable categories and explains each distribution in detail. Toward the end, you will learn how to install Minikube using Docker as the driver, with full explanations of every installation command.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understanding Kubernetes Flavors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes distributions differ primarily in:&lt;/li&gt;
&lt;li&gt;Deployment model (on-prem, cloud, hybrid, edge)&lt;/li&gt;
&lt;li&gt;Support level (commercial vs. community)&lt;/li&gt;
&lt;li&gt;Extra features (UI dashboards, multi-cluster management, security tools, lifecycle automation)&lt;/li&gt;
&lt;li&gt;Operational complexity&lt;/li&gt;
&lt;li&gt;Integration with cloud-native tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make the choice easier, we classify them into four practical categories:&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Kubernetes Distribution Categories
&lt;/h2&gt;

&lt;h2&gt;
  
  
  CATEGORY A — Commercial, Enterprise-Supported Kubernetes Distributions
&lt;/h2&gt;

&lt;p&gt;These are paid Kubernetes platforms built for production workloads, strict compliance, zero-downtime upgrades, global scalability, and enterprise SLAs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Red Hat OpenShift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Type: Commercial enterprise Kubernetes&lt;br&gt;
Best for: Large enterprises, secure environments, regulated industries&lt;br&gt;
Why it stands out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built on Kubernetes with many enterprise features added&lt;/li&gt;
&lt;li&gt;Includes CI/CD, service mesh, registries, security scanning&lt;/li&gt;
&lt;li&gt;Comes with an opinionated workflow&lt;/li&gt;
&lt;li&gt;Strong multi-cluster management (via ACM)&lt;/li&gt;
&lt;li&gt;Runs on-prem, cloud, or hybrid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenShift is essentially “Kubernetes with batteries included,” removing most manual configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ VMware Tanzu Kubernetes Grid (TKG)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Type: Commercial enterprise Kubernetes&lt;br&gt;
Best for: VMware-based data centers &amp;amp; enterprises&lt;br&gt;
Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep integration with vSphere&lt;/li&gt;
&lt;li&gt;Automated cluster lifecycle management&lt;/li&gt;
&lt;li&gt;Multi-cloud capability&lt;/li&gt;
&lt;li&gt;Strong enterprise governance and policy automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TKG is ideal for organizations already invested in VMware infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ SUSE Rancher Prime (Enterprise Rancher)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Type: Paid, enterprise version of Rancher&lt;br&gt;
Best for: Managing many Kubernetes clusters across different environments&lt;br&gt;
Key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Central management plane&lt;/li&gt;
&lt;li&gt;RBAC, audit, monitoring, Istio service mesh&lt;/li&gt;
&lt;li&gt;Integrates with RKE (Rancher Kubernetes Engine)&lt;/li&gt;
&lt;li&gt;Production support included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rancher simplifies multi-cluster operations for enterprises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Canonical Kubernetes (Kubeadm + Canonical Support)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Type: Commercial support for upstream Kubernetes&lt;br&gt;
Best for: Businesses using Ubuntu-based infrastructure&lt;br&gt;
Highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight and fast&lt;/li&gt;
&lt;li&gt;Comes with long-term support&lt;/li&gt;
&lt;li&gt;Ideal for on-prem and air-gapped setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is pure upstream Kubernetes with professional support.&lt;/p&gt;
&lt;h2&gt;
  
  
  CATEGORY B — CNCF-Certified Open-Source Distributions
&lt;/h2&gt;

&lt;p&gt;(Enterprise-Grade but Free)&lt;/p&gt;

&lt;p&gt;These are open-source, production-ready platforms but may require paid support optionally. They follow the CNCF Kubernetes Conformance Program, meaning they behave like true Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Kubernetes (Upstream - K8s The Hard Way)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the pure version maintained by CNCF.&lt;br&gt;
No UI, no extras, just Kubernetes.&lt;br&gt;
Suitable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learning internals&lt;/li&gt;
&lt;li&gt;Highly-custom deployments&lt;/li&gt;
&lt;li&gt;Research&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✔ K3s (Lightweight Kubernetes by SUSE)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why it is unique:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely small footprint&lt;/li&gt;
&lt;li&gt;Optimized for IoT, Edge &amp;amp; ARM devices&lt;/li&gt;
&lt;li&gt;Single binary installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;K3s is becoming the default Kubernetes for edge computing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ RKE (Rancher Kubernetes Engine)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Kubernetes distribution maintained by Rancher.&lt;br&gt;
Designed for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Fast bootstrap&lt;/li&gt;
&lt;li&gt;On-prem clusters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RKE is often used together with Rancher for management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ K0s (Zero Friction Kubernetes by Mirantis)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A minimal, single-binary Kubernetes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No OS dependencies&lt;/li&gt;
&lt;li&gt;Very easy deployment&lt;/li&gt;
&lt;li&gt;GitOps support built-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Favored for edge and Kubernetes appliances.&lt;/p&gt;
&lt;h2&gt;
  
  
  CATEGORY C — Cloud Provider Kubernetes Services
&lt;/h2&gt;

&lt;p&gt;(Managed Kubernetes)&lt;/p&gt;

&lt;p&gt;These are Kubernetes platforms offered fully as a service. The cloud provider maintains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;control plane&lt;/li&gt;
&lt;li&gt;security patches&lt;/li&gt;
&lt;li&gt;upgrades&lt;/li&gt;
&lt;li&gt;availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only manage worker nodes and workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Amazon Elastic Kubernetes Service (EKS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS's managed Kubernetes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High availability control plane&lt;/li&gt;
&lt;li&gt;Native integration with IAM, VPC, Load Balancers, ECR&lt;/li&gt;
&lt;li&gt;Auto-scaling across AZs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Used heavily in production due to AWS's ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Google Kubernetes Engine (GKE)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google created Kubernetes, so GKE is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The most mature managed Kubernetes&lt;/li&gt;
&lt;li&gt;Very stable, very scalable&lt;/li&gt;
&lt;li&gt;Offers autopilot mode (serverless Kubernetes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Often considered the best managed Kubernetes in the industry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Azure Kubernetes Service (AKS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strongly integrated with Azure Cloud with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AAD authentication&lt;/li&gt;
&lt;li&gt;Azure Monitor&lt;/li&gt;
&lt;li&gt;Automated node scaling&lt;/li&gt;
&lt;li&gt;Windows container support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for enterprises using Microsoft environments.&lt;/p&gt;

&lt;p&gt;✔ Oracle OKE, IBM IKS, DigitalOcean DOKS&lt;/p&gt;

&lt;p&gt;All offer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managed control planes&lt;/li&gt;
&lt;li&gt;Autoscaling&lt;/li&gt;
&lt;li&gt;Node pools&lt;/li&gt;
&lt;li&gt;Cloud-native integrations
These are great for teams who want Kubernetes without managing infrastructure.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  CATEGORY D — Local Developer-Focused Kubernetes Options
&lt;/h2&gt;

&lt;p&gt;These are for learning, testing, and local development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Minikube&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lightweight single-node Kubernetes cluster&lt;br&gt;
Runs on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It supports multiple drivers (VirtualBox, Docker, Hyper-V).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✔ Kind (Kubernetes IN Docker)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Allows spinning up Kubernetes clusters inside Docker containers.&lt;br&gt;
Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;Testing multiple cluster versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MicroK8s&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Canonical’s single-node Kubernetes&lt;br&gt;
Good for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local development&lt;/li&gt;
&lt;li&gt;Edge computing&lt;/li&gt;
&lt;li&gt;High availability (with clustering enabled)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Summary Table: Kubernetes Distribution Categories&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%2F840rhuwv92ikruw28s39.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%2F840rhuwv92ikruw28s39.png" alt="Kubernetes distribution" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Installing Minikube (Using Docker as the Driver)
&lt;/h2&gt;

&lt;p&gt;Below is a complete guide. Every command is followed by a detailed explanation.&lt;/p&gt;

&lt;p&gt;Minikube allows you to run a local Kubernetes cluster on your machine and is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;learning Kubernetes&lt;/li&gt;
&lt;li&gt;testing applications before deploying&lt;/li&gt;
&lt;li&gt;experimenting with operators and CRDs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Setup (Ubuntu/WSL)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When working with Kubernetes locally, Minikube is one of the most popular tools to spin up a lightweight cluster. If you are using Windows and Visual Studio Code, the most reliable way to prepare your environment is by leveraging the Windows Subsystem for Linux (WSL). This ensures you have a proper Linux shell inside Windows, which makes installing and running Minikube seamless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install WSL&lt;/strong&gt;&lt;br&gt;
Begin by opening PowerShell as Administrator and running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command installs WSL along with a default Linux distribution (usually Ubuntu). After installation, restart your machine to finalize the setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Connect VS Code to WSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open Visual Studio Code and install the Remote – WSL extension. This allows you to connect directly to your Ubuntu environment from within VS Code. Once connected, you’ll be working inside a Linux terminal without leaving your Windows setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Update your package index&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;sudo apt update

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Explanation:&lt;/em&gt;&lt;br&gt;
This command refreshes Ubuntu’s knowledge of available packages.&lt;br&gt;
It does not upgrade anything; it only updates the package list.&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%2Fff1kpdxurbvqqgsxhkzs.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%2Fff1kpdxurbvqqgsxhkzs.png" alt="sudo update" width="800" height="678"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Install Docker (Recommended Driver for Minikube)&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;sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

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

&lt;/div&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%2Fgvwkeaa2toxidpnywh7q.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%2Fgvwkeaa2toxidpnywh7q.png" alt="docker app" width="800" height="435"&gt;&lt;/a&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%2Fhq8wf1uo8ky1igloc0lj.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%2Fhq8wf1uo8ky1igloc0lj.png" alt="Docker enable" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sudo apt install docker.io installs Docker CE from Ubuntu repos&lt;/li&gt;
&lt;li&gt;sudo systemctl start docker starts the Docker service&lt;/li&gt;
&lt;li&gt;sudo systemctl enable docker ensures Docker automatically starts on boot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker is the recommended Minikube driver because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is lightweight&lt;/li&gt;
&lt;li&gt;fast&lt;/li&gt;
&lt;li&gt;easy to manage&lt;/li&gt;
&lt;li&gt;integrates smoothly with Kubernetes workloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Download Minikube Binary&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;curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

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

&lt;/div&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%2Fck3bcgpvgq4lxzxji1vx.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%2Fck3bcgpvgq4lxzxji1vx.png" alt="minikube download" width="800" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;curl -LO downloads the latest Minikube binary&lt;/li&gt;
&lt;li&gt;sudo install places it into /usr/local/bin and makes it executable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this, you should be able to run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube version

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

&lt;/div&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%2Fgkubeu06962h3majh4zf.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%2Fgkubeu06962h3majh4zf.png" alt="Comfirmation of minikube installation" width="800" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6 — Install kubectl (The Kubernetes CLI) Properly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes changed its repo structure in 2023–2024, so older tutorials are broken.&lt;br&gt;
Here is the correct method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg

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

&lt;/div&gt;



&lt;p&gt;These packages allow secure HTTPS repository management.&lt;/p&gt;

&lt;p&gt;Add the new Kubernetes signing key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

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

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;br&gt;
Downloads the GPG key and converts it to a format apt can use for validating packages.&lt;/p&gt;

&lt;p&gt;Add the Kubernetes repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
  https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /" \
  | sudo tee /etc/apt/sources.list.d/kubernetes.list

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

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;br&gt;
Creates a new repo file so Ubuntu knows where to fetch kubectl.&lt;/p&gt;

&lt;p&gt;Install kubectl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install -y kubectl

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

&lt;/div&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%2F9e4teueg5cpd9dy0bcy4.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%2F9e4teueg5cpd9dy0bcy4.png" alt="Kubect Update" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 7 — Start Minikube with Docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start --driver=docker

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

&lt;/div&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%2Fz3486x9yb8ccz7y35i1t.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%2Fz3486x9yb8ccz7y35i1t.png" alt="Minikube start docker" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What this does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializes Minikube&lt;/li&gt;
&lt;li&gt;Uses Docker as the virtualization layer&lt;/li&gt;
&lt;li&gt;Creates a Linux VM-like environment inside Docker&lt;/li&gt;
&lt;li&gt;Deploys a full single-node Kubernetes cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After successful startup, you can verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get nodes

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

&lt;/div&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%2F26h0q9xfmks9gug1phvm.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%2F26h0q9xfmks9gug1phvm.png" alt="Kubeck Node" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: if you just installed Minikube and Docker, you might need to restart your terminal or run :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval $(minikube -p minikube docker-env)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the following Code in this order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start --driver=docker
kubectl config use-context minikube
minikube status
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes has evolved into a rich ecosystem with many flavors, each optimized for different environments—from enterprise production (OpenShift, Tanzu, Rancher Prime) to cloud-managed solutions (AKS/EKS/GKE) and lightweight edge platforms (K3s, K0s).&lt;/p&gt;

&lt;p&gt;However, for local learning and experimentation, Minikube remains the best starting point.&lt;br&gt;
The installation guide provided above ensures that you set it up using the most reliable driver—Docker—while following best practices for installing kubectl.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>msbuild</category>
      <category>docker</category>
      <category>skillsch</category>
    </item>
    <item>
      <title>Mastering Ubuntu: The Essential Commands You Need to Know</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sun, 28 Sep 2025 02:25:46 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/mastering-ubuntu-the-essential-commands-you-need-to-know-5097</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/mastering-ubuntu-the-essential-commands-you-need-to-know-5097</guid>
      <description>&lt;p&gt;*&lt;em&gt;Introduction *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Whether you're just dipping your toes into Linux or managing a full-blown Ubuntu server, knowing your way around the terminal is non-negotiable. In this guide, we’ll walk through the most essential Ubuntu commands—step by step—explaining not just how to use them, but why they matter. From installing packages to navigating directories and monitoring system health, this article is your launchpad into the world of Linux command-line mastery.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐧 Essential Ubuntu Commands Explained Step-by-Step
&lt;/h2&gt;

&lt;p&gt;Ubuntu is one of the most popular Linux distributions, widely used for development, server management, and learning Linux fundamentals. Below is a breakdown of key commands every Ubuntu user should know, what they do, and why they’re important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 sudo su&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Switches to the superuser (root) account.&lt;/li&gt;
&lt;li&gt;Why it matters: Some tasks require elevated privileges. sudo su gives you full access to the system.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll be prompted for your password. Once entered, your shell changes to root (# prompt). &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%2Fj92grtokr5u8uynx4avc.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%2Fj92grtokr5u8uynx4avc.png" alt="Sudocommand" width="779" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📦 Package Management&lt;/strong&gt;&lt;br&gt;
apt update&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Refreshes the list of available packages and versions.&lt;/li&gt;
&lt;li&gt;Why it matters: Ensures you're installing the latest versions.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fclnksdraypg60v0x4e57.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%2Fclnksdraypg60v0x4e57.png" alt="apt update" width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;apt install vim&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Installs the Vim text editor.&lt;/li&gt;
&lt;li&gt;Why it matters: Vim is a powerful tool for editing configuration files and code.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fp6hol70vsxv73ajwbp8w.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%2Fp6hol70vsxv73ajwbp8w.png" alt="vim" width="616" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;apt install nginx&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Installs the Nginx web server.&lt;/li&gt;
&lt;li&gt;Why it matters: Nginx is widely used for hosting websites and reverse proxying.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5fwl1i8bxuidqx0lwyfk.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%2F5fwl1i8bxuidqx0lwyfk.png" alt="nginx" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📁 File &amp;amp; Directory Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;mkdir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Creates a new directory.&lt;/li&gt;
&lt;li&gt;Why it matters: Organize files into folders.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir my_folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ls&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Lists files and directories.&lt;/li&gt;
&lt;li&gt;Why it matters: Helps you see what’s in your current directory.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2F8a9mesa3b5iqb12bjm6v.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%2F8a9mesa3b5iqb12bjm6v.png" alt="Iist" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;cd&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Changes the current directory.&lt;/li&gt;
&lt;li&gt;Why it matters: Navigate your file system.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my_folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F2drmik11sisqp9fkh9d9.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%2F2drmik11sisqp9fkh9d9.png" alt="Cd folder" width="598" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ls -l&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Lists files with detailed info (permissions, size, date).&lt;/li&gt;
&lt;li&gt;Why it matters: Useful for checking file attributes.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fczqqt4ilp7ebgv6thguv.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%2Fczqqt4ilp7ebgv6thguv.png" alt="hinding list" width="490" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;pwd&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Prints the current working directory.&lt;/li&gt;
&lt;li&gt;Why it matters: Know where you are in the file system.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2Fqsa3sraehphsyzykucf9.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%2Fqsa3sraehphsyzykucf9.png" alt="pwd" width="639" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;touch&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Creates an empty file.&lt;/li&gt;
&lt;li&gt;Why it matters: Useful for quickly generating files.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch myfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8404ke5xae25opjpwmqa.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%2F8404ke5xae25opjpwmqa.png" alt="touch" width="510" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;rm&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Deletes files.&lt;/li&gt;
&lt;li&gt;Why it matters: Clean up unnecessary files.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm myfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rmdir&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Removes empty directories.&lt;/li&gt;
&lt;li&gt;Why it matters: Helps maintain a tidy file structure.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rmdir my_folder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F75f349vypliy6y99c03t.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%2F75f349vypliy6y99c03t.png" alt="rmdelete" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;cp&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Copies files or directories.&lt;/li&gt;
&lt;li&gt;Why it matters: Duplicate files or back them up.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp file1.txt file2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fb97wso20ptueyni1qubf.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%2Fb97wso20ptueyni1qubf.png" alt="coping" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;mv&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Moves or renames files.&lt;/li&gt;
&lt;li&gt;Why it matters: Organize or rename files.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv oldname.txt newname.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fop7nfbukvtiwslq1t5mg.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%2Fop7nfbukvtiwslq1t5mg.png" alt="move" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📊 System Monitoring&lt;/strong&gt;&lt;br&gt;
df -h&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Shows disk space usage in human-readable format.&lt;/li&gt;
&lt;li&gt;Why it matters: Monitor storage capacity.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fedinfh8myszirgaqb8ao.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%2Fedinfh8myszirgaqb8ao.png" alt=" " width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;free -h&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Displays memory usage.&lt;/li&gt;
&lt;li&gt;Why it matters: Check RAM availability.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;free -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F393ybavi54f1r9h7hteb.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%2F393ybavi54f1r9h7hteb.png" alt="memory usage" width="592" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;uptime&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Shows how long the system has been running.&lt;/li&gt;
&lt;li&gt;Why it matters: Useful for server health checks.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2Ftysm5ujdvbcgju7ne19l.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%2Ftysm5ujdvbcgju7ne19l.png" alt="monitor" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔍 Searching &amp;amp; Environment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;grep&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Searches for patterns in text.&lt;/li&gt;
&lt;li&gt;Why it matters: Find specific data in files or output.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep "search_term" filename.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;env&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Displays environment variables.&lt;/li&gt;
&lt;li&gt;Why it matters: Useful for debugging and configuration.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2F9h07lsbhz2elcu160ul0.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%2F9h07lsbhz2elcu160ul0.png" alt="environment variables" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;whoami&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Shows the current user.&lt;/li&gt;
&lt;li&gt;Why it matters: Confirm your identity, especially after switching users.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2F1z8wq4i4izodnwtcw9en.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%2F1z8wq4i4izodnwtcw9en.png" alt="who ami" width="421" height="55"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌐 Networking&lt;/strong&gt;&lt;br&gt;
nslookup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Queries DNS to resolve domain names.&lt;/li&gt;
&lt;li&gt;Why it matters: Diagnose network issues.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nslookup example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4ej94x50pjrmgn873ky0.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%2F4ej94x50pjrmgn873ky0.png" alt="nslookup" width="596" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ping&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Sends packets to a host to test connectivity.&lt;/li&gt;
&lt;li&gt;Why it matters: Check if a server or website is reachable.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ping google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;System Info &amp;amp; File Viewing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;uname&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Displays system information.&lt;/li&gt;
&lt;li&gt;Why it matters: Know your OS and kernel version.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uname -a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvtgfkhn4waeymvbcg6zn.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%2Fvtgfkhn4waeymvbcg6zn.png" alt="Iinux" width="800" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;cat&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Displays file content.&lt;/li&gt;
&lt;li&gt;Why it matters: Quickly read files.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat myfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fw6aq7wxw8va3h4vcujv5.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%2Fw6aq7wxw8va3h4vcujv5.png" alt="cat file" width="522" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;df&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does: Shows disk usage (not human-readable by default).&lt;/li&gt;
&lt;li&gt;Why it matters: Monitor storage.&lt;/li&gt;
&lt;li&gt;How to use:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2Ftgh6qmjhunlkurpf3tk3.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%2Ftgh6qmjhunlkurpf3tk3.png" alt="show disk usage" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Mastering these commands will give you a solid foundation in Ubuntu and Linux in general. Whether you're managing servers, writing scripts, or just exploring, these tools are your gateway to understanding and controlling your system.&lt;/p&gt;

</description>
      <category>skillch</category>
      <category>beginners</category>
      <category>linux</category>
      <category>github</category>
    </item>
    <item>
      <title>Creating DNS Zones and Configuring DNS Settings in Azure</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Mon, 15 Sep 2025 17:16:17 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/creating-dns-zones-and-configuring-dns-settings-in-azure-36d3</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/creating-dns-zones-and-configuring-dns-settings-in-azure-36d3</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;In modern cloud environments, relying on IP addresses for internal communication is both inefficient and prone to errors. Organizations increasingly prefer using domain names for better readability, scalability, and manageability. Azure offers a built-in solution—Azure Private DNS—that enables secure, internal name resolution without deploying custom DNS servers.&lt;/p&gt;

&lt;p&gt;This guide walks you through the process of creating and configuring a Private DNS zone, linking it to a virtual network, and setting up DNS records. Each step is explained not just technically, but also strategically—so you understand the why behind the how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario Overview&lt;/strong&gt;&lt;br&gt;
Your organization has the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal workloads must use domain names instead of IP addresses.&lt;/li&gt;
&lt;li&gt;No custom DNS solution should be added.&lt;/li&gt;
&lt;li&gt;A Private DNS zone is needed for contoso.com.&lt;/li&gt;
&lt;li&gt;The zone must be linked to the app-vnet virtual network.&lt;/li&gt;
&lt;li&gt;A DNS record is required for the backend subnet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skilling Tasks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and configure a Private DNS zone&lt;/li&gt;
&lt;li&gt;Create and configure DNS records&lt;/li&gt;
&lt;li&gt;Configure DNS settings on a virtual network&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Create a Private DNS Zone
&lt;/h2&gt;

&lt;p&gt;Azure Private DNS provides a reliable, secure DNS service to manage and resolve domain names in a virtual network without the need to add a custom DNS solution. By using private DNS zones, you can use your own custom domain names rather than the Azure-provided names.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Azure portal, search for and select Private DNS zones.&lt;/li&gt;
&lt;/ol&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%2Ftspl7gcawbmw9r15bvko.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%2Ftspl7gcawbmw9r15bvko.png" alt="private" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Select + Create and configure the DNS zone.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                Value
Subscription            Select your subscription
Resource group          RG1
Name                    private.contoso.com
Region                  West US 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;3. Select Review + create and then select Create.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;4. Wait for the DNS zone to deploy, and then select Go to resource.&lt;/em&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%2Fcbjytlintri4lc3sndf5.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%2Fcbjytlintri4lc3sndf5.png" alt="dnscreate" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Link the DNS Zone to a Virtual Network
&lt;/h2&gt;

&lt;p&gt;To resolve DNS records in a private DNS zone, resources must be linked to the private zone. A virtual network link associates the virtual network to the private zone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the portal, continue working on the private.contoso.com DNS zone.&lt;/li&gt;
&lt;li&gt;In the DNS Management blade, select + Virtual network links.&lt;/li&gt;
&lt;li&gt;Select + Add” and configure the virtual network link.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;![Addon Virtuallink(&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ir2fa2dznm1cp23xkukl.png" rel="noopener noreferrer"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ir2fa2dznm1cp23xkukl.png&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Select Create and wait for the deployment to finish. If necessary, Refresh the page.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Property                  Value
Link name                 app-vnet-link
Virtual network               app-vnet
Enable auto registration      Enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Foavag20d7kq7t3cn330v.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%2Foavag20d7kq7t3cn330v.png" alt="createlink" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create a DNS Record Set
&lt;/h2&gt;

&lt;p&gt;DNS records map domain names to IP addresses. Creating an A record for the backend subnet allows internal services to reach the backend VM using a friendly name like backend.private.contoso.com.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                Value
Name                    backend
Type                A
TTL                 1
IP address          10.1.1.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fy78bznmmqa0txse5trfs.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%2Fy78bznmmqa0txse5trfs.png" alt=" " width="800" height="366"&gt;&lt;/a&gt;&lt;br&gt;
Note: This record set implies there is a virtual machine in app-vnet with a private IP address of 10.1.1.5.&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%2F3tyovylikjo8oa6wcl32.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%2F3tyovylikjo8oa6wcl32.png" alt="Record set" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;br&gt;
Congratulations on completing the exercise. Here are the main takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Azure DNS is a cloud service that allows you to host and manage domain name system (DNS) domains, also known as DNS zones.&lt;/li&gt;
&lt;li&gt;Azure DNS public zones host domain name zone data for records that you intend to be resolved by any host on the internet.&lt;/li&gt;
&lt;li&gt;Azure Private DNS zones allow you to configure a private DNS zone namespace for private Azure resources.&lt;/li&gt;
&lt;li&gt;A DNS zone is a collection of DNS records. DNS records provide information about the domain.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>skillch</category>
      <category>mslearn</category>
      <category>computerscience</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Configuring Network Routing in Azure: Enforcing Firewall Policies with Custom Routes</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sun, 14 Sep 2025 23:51:10 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/configuring-network-routing-in-azure-enforcing-firewall-policies-with-custom-routes-72p</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/configuring-network-routing-in-azure-enforcing-firewall-policies-with-custom-routes-72p</guid>
      <description>&lt;p&gt;As cloud applications grow in complexity and exposure, enforcing centralized security policies becomes essential. One of the most effective ways to do this in Azure is by routing outbound traffic through a firewall using custom route tables. This article walks you through the process of configuring network routing to ensure that all outbound traffic from your application subnets is filtered through Azure Firewall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario Overview&lt;/strong&gt;&lt;br&gt;
Your organization has deployed an application in Azure using a virtual network (app-vnet) with two subnets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend subnet: Hosts web servers.&lt;/li&gt;
&lt;li&gt;Backend subnet: Hosts database servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To enforce firewall policies, all outbound traffic from these subnets must be routed through Azure Firewall using its private IP address. This requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a custom route table.&lt;/li&gt;
&lt;li&gt;Associating the route table with both subnets.&lt;/li&gt;
&lt;li&gt;Defining a user-defined route (UDR) that redirects traffic to the firewall.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Record the Firewall’s Private IP Address
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What You Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Azure portal, search for Firewall.&lt;/li&gt;
&lt;li&gt;Select your firewall instance (app-vnet-firewall).&lt;/li&gt;
&lt;li&gt;Go to Overview and note the Private IP address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
This IP address will be used as the next hop in your custom route. It ensures that traffic is redirected to the firewall for inspection before leaving the virtual network.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Create a Custom Route Table
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the search box, enter Route tables. When Route table appears in the search results, select it.&lt;/li&gt;
&lt;/ol&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%2Fr7574vwnmw8lq7xzoqna.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%2Fr7574vwnmw8lq7xzoqna.png" alt="routetabe" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. In the Route table page, select + Create and create the route table.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property            Value
Subscription            Select your subscription
Resource group      RG1
Region                  West US 3
Name                    app-vnet-firewall-rt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;3. Select Review + create and then select Create.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;4. Wait for the route table to deploy, then select Go to resource.&lt;/em&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%2Fh1zhppruc1r1jp9fdt06.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%2Fh1zhppruc1r1jp9fdt06.png" alt="create table route" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
Azure automatically creates system route tables for each subnet, but these default routes don’t enforce firewall policies. A custom route table allows you to override system routes and direct traffic through a Network Virtual Appliance (NVA) like Azure Firewall.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Associate the Route Table with Subnets
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the portal, continue working with the route table, select app-vnet-firewall-rt.&lt;/li&gt;
&lt;li&gt;In the Settings blade, select Subnets and then + Associate.&lt;/li&gt;
&lt;li&gt;Configure an association to the frontend subnet, then select OK.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                   Value
Virtual network                app-vnet (RG1)
Subnet                         frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fsg8bo3lal33titjkkhb7.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%2Fsg8bo3lal33titjkkhb7.png" alt="associatefront" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Configure an association to the backend subnet, then select OK.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Property                  Value
Virtual network               app-vnet (RG1)
Subnet                        backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi907vil8jz9442gjssmg.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%2Fi907vil8jz9442gjssmg.png" alt="associate back" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Associating the route table with both subnets ensures that all outbound traffic from these subnets follows the custom route you’ll define next. Without this association, the route won’t apply.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 4: Create a User-Defined Route (UDR)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the portal, continue working with the route table, select app-vnet-firewall-rt.&lt;/li&gt;
&lt;li&gt;In the Settings blade, select Routes and then + Add.&lt;/li&gt;
&lt;li&gt;Configure the route, then select Add.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                        Value
Route name                      outbound-firewall
Destination type                    IP addresses
Destination IP addresses/CIDR range 0.0.0.0/0
Next hop type                       Virtual appliance
Next hop address                private IP address of the firewall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fqq0860rbcc90givxl97y.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%2Fqq0860rbcc90givxl97y.png" alt="route table" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
This route captures all outbound traffic (0.0.0.0/0) and redirects it to the firewall. The Virtual appliance hop type tells Azure to send traffic to a custom IP—your firewall—rather than directly to the internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Architecture Matters&lt;/strong&gt;&lt;br&gt;
By routing traffic through Azure Firewall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You enforce centralized security policies.&lt;/li&gt;
&lt;li&gt;You gain visibility into outbound traffic.&lt;/li&gt;
&lt;li&gt;You can apply application-level filtering, threat detection, and logging.&lt;/li&gt;
&lt;li&gt;You reduce the risk of data exfiltration or unauthorized access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup is especially critical for organizations using DevOps pipelines, external APIs, or internet-facing applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
Routing in Azure isn’t just about connectivity—it’s about control. By configuring custom route tables and directing traffic through Azure Firewall, you build a secure, scalable, and compliant network architecture. Whether you're protecting sensitive data or managing complex workloads, this approach gives you the power to shape how traffic flows—and how threats are stopped.&lt;/p&gt;

</description>
      <category>skillch</category>
      <category>beginners</category>
      <category>cloud</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Securing Azure Workloads with Azure Firewall: A Step-by-Step Implementation Guide</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sun, 14 Sep 2025 22:07:59 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/securing-azure-workloads-with-azure-firewall-a-step-by-step-implementation-guide-4cd4</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/securing-azure-workloads-with-azure-firewall-a-step-by-step-implementation-guide-4cd4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As cloud applications scale, so do the threats they face. From unauthorized access to data exfiltration, the need for centralized, intelligent network security becomes non-negotiable. Enter Azure Firewall—a robust, cloud-native solution that offers deep packet inspection, application-level filtering, and threat intelligence.&lt;/p&gt;

&lt;p&gt;In this guide, we walk through the deployment and configuration of Azure Firewall to protect an application virtual network (app-vnet). Each step is explained with its technical purpose and strategic value, so you can build not just a secure network—but a resilient one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario Overview
&lt;/h2&gt;

&lt;p&gt;Your organization is preparing for increased application usage and continuous integration via Azure DevOps. To meet these demands securely, you’ve identified the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy Azure Firewall in app-vnet for centralized security.&lt;/li&gt;
&lt;li&gt;Create a Firewall Policy to manage access rules.&lt;/li&gt;
&lt;li&gt;Add an Application Rule to allow access to Azure DevOps.&lt;/li&gt;
&lt;li&gt;Add a Network Rule to enable DNS resolution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create Azure Firewall subnet in our existing virtual network
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the search box at the top of the portal, enter Virtual networks. Select Virtual networks in the search results.&lt;/li&gt;
&lt;li&gt;Select app-vnet.&lt;/li&gt;
&lt;li&gt;Select Subnets.&lt;/li&gt;
&lt;li&gt;Select + Subnet.&lt;/li&gt;
&lt;li&gt;Enter the following information and select Save.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Property                      Value**
Name                                AzureFirewallSubnet
Address range                       10.1.63.0/26
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Leave all other settings as default.&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%2Ftdy7c7umu6bx70nd7g9t.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%2Ftdy7c7umu6bx70nd7g9t.png" alt="Azurefirewall" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create an Azure Firewall
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the search box at the top of the portal, enter Firewall. Select Firewall in the search results.&lt;/li&gt;
&lt;li&gt;Select + Create.&lt;/li&gt;
&lt;/ol&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%2Fxyeltq0jxur4ls1tou4d.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%2Fxyeltq0jxur4ls1tou4d.png" alt="firecreate" width="800" height="282"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;3. Create a firewall by using the values in the following table. For any property that is not specified, use the default value.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Azure Firewall can take a few minutes to deploy.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Property              Value**
Resource group              RG1
Name                        app-vnet-firewall
Firewall SKU                Standard
Firewall management     Use a Firewall Policy to manage this firewall
Firewall policy             select Add new
Policy name             fw-policy
Region                      West US 3
Policy Tier             Standard
Choose a virtual network     Use existing
Virtual network              app-vnet (RG1)
Public IP address        Add new: fwpip
Enable Firewall Management NIC  uncheck the box
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fw4x0xhd67xq4dyetmqgn.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%2Fw4x0xhd67xq4dyetmqgn.png" alt="policy 1" width="800" height="365"&gt;&lt;/a&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%2Fyec1obcp10ge9eqs6k6c.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%2Fyec1obcp10ge9eqs6k6c.png" alt="firewall2" width="800" height="365"&gt;&lt;/a&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%2Fe2arzmxwoj6jrzuhdu0i.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%2Fe2arzmxwoj6jrzuhdu0i.png" alt="fwpol" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Select Review + create and then select Create.&lt;/em&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%2Fzbi03nbmtn20dgptevha.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%2Fzbi03nbmtn20dgptevha.png" alt="Created" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3: Configure the Firewall Policy&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the portal, search for and select Firewall Policies.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;fw-policy&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2Frqtiv4s8z89i7a9khido.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%2Frqtiv4s8z89i7a9khido.png" alt="firewall polcie" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3a: Add an Application Rule&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Settings blade, select Application rules and then Add a rule collection.&lt;/li&gt;
&lt;li&gt;Configure the application rule collection and then select Add.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                   Value
Name                            app-vnet-fw-rule-collection
Rule collection type             Application
Priority                     200
Rule collection action           Allow
Rule collection group            DefaultApplicationRuleCollectionGroup
Name                             AllowAzurePipelines
Source type                  IP address
Source                           10.1.0.0/23
Protocol                     https
Destination type             FQDN
Destination                  dev.azure.com, azure.microsoft.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The AllowAzurePipelines rule allows the web application to access Azure Pipelines. The rule allows the web application to access the Azure DevOps service and the Azure website.&lt;/p&gt;
&lt;/blockquote&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%2Fe5fmgyoizj0rtzpn1h5d.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%2Fe5fmgyoizj0rtzpn1h5d.png" alt="applicationrule" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why It Matters:&lt;br&gt;
&lt;em&gt;This rule allows your application servers to securely connect to Azure DevOps for continuous updates. Using FQDN filtering, Azure Firewall can inspect outbound traffic and allow only specific domains—critical for reducing exposure to malicious sites.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3b: Add a Network Rule&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Settings blade, select Network rules and then Add a network collection.&lt;/li&gt;
&lt;li&gt;Configure the network rule and then select Add.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Property                Value
Name                        app-vnet-fw-nrc-dns
Rule collection type        Network
Priority                200
Rule collection action      Allow
Rule collection group       DefaultNetworkRuleCollectionGroup
Rule                        AllowDns
Source                      10.1.0.0/23
Protocol                    UDP
Destination ports           53
Destination addresses       1.1.1.1, 1.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Frzvt4ss9bnsbgjtosl84.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%2Frzvt4ss9bnsbgjtosl84.png" alt="collectionrule" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DNS is the backbone of internet communication. Without it, your servers can’t resolve domain names. This rule ensures that your workloads can reach Cloudflare’s DNS servers securely, enabling name resolution for outbound traffic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Verify Deployment Status
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the portal search for and select Firewall.&lt;/li&gt;
&lt;li&gt;View the app-vnet-firewall and ensure the Provisioning state is Succeeded. This may take a few minutes.&lt;/li&gt;
&lt;/ol&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%2Fdzkd1jdpnuklzo6ml11h.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%2Fdzkd1jdpnuklzo6ml11h.png" alt="provisioningstate" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the portal serach for and select Firewall policies.&lt;/li&gt;
&lt;li&gt;View the fw-policy and ensure the Provisioning state is Succeeded. This may take a few minutes.&lt;/li&gt;
&lt;/ol&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%2Fw59vlvi4onm4r3omyt6r.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%2Fw59vlvi4onm4r3omyt6r.png" alt="wallpolicies" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Successful provisioning confirms that your firewall is active and ready to enforce rules. This step ensures that your security posture is operational before workloads begin communicating.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Congratulations on completing the exercise. Here are the main takeaways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure Firewall is a cloud-based security service that protects your Azure virtual network resources from incoming and outgoing threats.&lt;/li&gt;
&lt;li&gt;An Azure firewall policy is a resource that contains one or more collections of NAT, network, and application rules.&lt;/li&gt;
&lt;li&gt;Network rules allow or deny traffic based on IP addresses, ports, and protocols.&lt;/li&gt;
&lt;li&gt;Application rules allow or deny traffic based on fully qualified domain names (FQDNs), URLs, and HTTP/HTTPS protocols.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>skillch</category>
      <category>devops</category>
      <category>azure</category>
      <category>mslearn</category>
    </item>
    <item>
      <title>Create the network infrastructure for the exercise</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sun, 14 Sep 2025 01:15:10 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/create-the-network-infrastructure-for-the-exercise-540k</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/create-the-network-infrastructure-for-the-exercise-540k</guid>
      <description>&lt;p&gt;As organizations migrate applications to the cloud, securing network traffic becomes a top priority. In this article, we walk through a practical scenario where an organization uses Network Security Groups (NSGs) and Application Security Groups (ASGs) to tightly control traffic within an Azure virtual network (app-vnet). This hands-on guide explains each step and the rationale behind it, helping you build a secure and manageable cloud environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario Overview&lt;/strong&gt;&lt;br&gt;
Your organization is deploying a web-based application in Azure. The architecture includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend subnet: Hosts web servers accessible from the internet.&lt;/li&gt;
&lt;li&gt;Backend subnet: Hosts database servers accessed only by the frontend.&lt;/li&gt;
&lt;li&gt;Virtual machines: VM1 in the frontend subnet, VM2 in the backend subnet.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security goals:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Group web servers using an ASG for simplified management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use an NSG to control traffic to the backend subnet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow secure SSH access from frontend to backend&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Deploy the Virtual Machines
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This exercise requires the Lab 01 virtual networks and subnets to be installed. A template is provided if you need to deploy those resources. (kindly refer to my previous post with this link &lt;a href="https://dev.to/isaiah_izibili_7a39b7d627/building-a-secure-network-architecture-in-azure-a-step-by-step-guide-3d8a"&gt;https://dev.to/isaiah_izibili_7a39b7d627/building-a-secure-network-architecture-in-azure-a-step-by-step-guide-3d8a&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Use the icon (top right) to launch a Cloud Shell session. Alternately, navigate directly to &lt;a href="https://shell.azure.com" rel="noopener noreferrer"&gt;https://shell.azure.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If prompted to select either Bash or PowerShell, select PowerShell.&lt;/li&gt;
&lt;li&gt;Storage is not required for this task Select your subscription. Apply your changes.&lt;/li&gt;
&lt;li&gt;Use these commands to deploy the virtual machines required for this exercise.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If the deployment fails for capacity restriction, edit the template and change the “location” value.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$RGName = "RG1"

New-AzResourceGroupDeployment -ResourceGroupName $RGName `
  -TemplateUri "https://raw.githubusercontent.com/MicrosoftLearning/Configure-secure-access-to-workloads-with-Azure-virtual-networking-services/main/Instructions/Labs/azuredeploy.json"

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;5. In the portal search for and select virtual machines. Verify both vm1 and vm2 are Running.&lt;/em&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%2F62n2e50siyvg06wlpbwb.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%2F62n2e50siyvg06wlpbwb.png" alt="VM" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why It Matters:&lt;br&gt;
This sets up the infrastructure needed to test and validate your security configurations. Using a template ensures consistency and saves time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Create an Application Security Group (ASG)
&lt;/h2&gt;

&lt;p&gt;Application security groups ASGs let you group VMs by function (e.g., web servers) and apply security rules to the group instead of individual IP addresses. This simplifies management and scales well.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the portal, search for and select Application security groups.&lt;/li&gt;
&lt;/ol&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%2Ftjthhitmadwgt9x8ww4r.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%2Ftjthhitmadwgt9x8ww4r.png" alt="Application security group" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Select + Create and configure the application security group.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Property          Value**
Subscription            Select your subscription
Resource group          RG1
Name                    app-frontend-asg
Region                  WEST US 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;3. Select Review + create and then select Create.&lt;/em&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%2Fzxkcoaib1iiqhcj9ul7o.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%2Fzxkcoaib1iiqhcj9ul7o.png" alt="Application security" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You are creating the application security group in the same region as the existing virtual network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Associate ASG with VM1
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure portal, search for and select VM1.&lt;/li&gt;
&lt;li&gt;In the Networking blade, select Application security groups and then select Add application security groups.&lt;/li&gt;
&lt;li&gt;Select the app-frontend-asg and then select Add.&lt;/li&gt;
&lt;/ol&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%2F2zqcvsyo1bfamda7m2un.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%2F2zqcvsyo1bfamda7m2un.png" alt="Application ASG" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create and Associate the Network Security Group
&lt;/h2&gt;

&lt;p&gt;NSGs are the backbone of Azure network security. They filter traffic using rules and can be applied to subnets or individual NICs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the portal search for and select Network security group.&lt;/li&gt;
&lt;li&gt;Select + Create and configure the network security group.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property              Value
Subscription              Select your subscription
Resource group            RG1
Name                      app-vnet-nsg
Region                    West US 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;3. Select Review + create and then select Create.&lt;/em&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%2Fn7z5k9doqlvu0m965o4e.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%2Fn7z5k9doqlvu0m965o4e.png" alt="INSG" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Associate the NSG with the app-vnet backend subnet.
&lt;/h2&gt;

&lt;p&gt;NSGs can be associated with subnets and/or individual network interfaces attached to Azure virtual machines.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select Go to resource or navigate to the app-vnet-nsg resource.&lt;/li&gt;
&lt;li&gt;In the Settings blade select Subnets.&lt;/li&gt;
&lt;li&gt;Select + Associate&lt;/li&gt;
&lt;li&gt;Select app-vnet (RG1) and then the Backend subnet. Select OK.&lt;/li&gt;
&lt;/ol&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%2Fqvd5b3xrkut1b355uccj.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%2Fqvd5b3xrkut1b355uccj.png" alt="Associat2" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Create Network Security Group rules
&lt;/h2&gt;

&lt;p&gt;An NSG use security rules to filter inbound and outbound network traffic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the search box at the top of the portal, enter Network security groups. Select Network security groups in the search results.&lt;/li&gt;
&lt;li&gt;Select app-vnet-nsg from the list of network security groups.&lt;/li&gt;
&lt;li&gt;In the Settings blade, select Inbound security rules.&lt;/li&gt;
&lt;li&gt;Select + Add and configure an inbound security rule.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property                               Value
Source                                 Any
Source port ranges                     *
Destination                            Application Security group
Destination application security group     app-frontend-asg
Service                                    SSH
Action                                     Allow
Priority                                   100
Name                                       AllowSSH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F3op89a9gk2mdf293o8yx.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%2F3op89a9gk2mdf293o8yx.png" alt="NetworkSG" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
This enables secure communication between web servers and database servers, while blocking all other traffic by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;br&gt;
Congratulations on completing the exercise. Here are the main takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Application security groups let you organize virtual machines and define network security policies based on your organization’s applications.&lt;/li&gt;
&lt;li&gt;An Azure network security group is used to filter network traffic between Azure resources in an Azure virtual network.&lt;/li&gt;
&lt;li&gt;You can associate zero, or one, network security group to each virtual network subnet and network interface in a virtual machine.&lt;/li&gt;
&lt;li&gt;A network security group contains security rules that allow or deny inbound network traffic to, or outbound network traffic from, Azure resources.&lt;/li&gt;
&lt;li&gt;You join virtual machines to an application security group. Then you use the application security group as a source or destination in the network security group rules.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>skillch</category>
      <category>mslearn</category>
      <category>devops</category>
      <category>azure</category>
    </item>
    <item>
      <title>Building a Secure Network Architecture in Azure: A Step-by-Step Guide</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Sat, 13 Sep 2025 20:51:02 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/building-a-secure-network-architecture-in-azure-a-step-by-step-guide-3d8a</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/building-a-secure-network-architecture-in-azure-a-step-by-step-guide-3d8a</guid>
      <description>&lt;p&gt;As organizations increasingly migrate applications to the cloud, designing a secure and scalable network architecture becomes critical. In this article, we walk through the process of setting up a hub-and-spoke architecture in Microsoft Azure, tailored for a web-based application deployment.&lt;/p&gt;

&lt;p&gt;Scenario overview &lt;br&gt;
Your organization is migrating a web-based application to Azure. The first step is to establish the foundational networking components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two virtual networks: app-vnet and hub-vnet, simulating a hub-and-spoke topology.&lt;/li&gt;
&lt;li&gt;app-vnet will host the application, split into:
&lt;em&gt;frontend-subnet for web servers&lt;/em&gt;
&lt;em&gt;backend-subnet for database servers&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;hub-vnet will contain a single firewall-subnet for centralized security.&lt;/li&gt;
&lt;li&gt;Both networks must be securely peered to allow private communication.&lt;/li&gt;
&lt;li&gt;All resources will reside in the same Azure region.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architecture diagram&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%2F7wvxycr6f4u1k8q5d2ek.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%2F7wvxycr6f4u1k8q5d2ek.png" alt="Task Diagram" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Create hub and spoke virtual networks and subnets
&lt;/h2&gt;

&lt;p&gt;An Azure virtual network enables many types of Azure resources to securely communicate with each other, the internet, and on-premises networks. All Azure resources in a virtual network are deployed into subnets within the virtual network.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign in to the Azure portal - &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;https://portal.azure.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Search for and select Virtual Networks.&lt;/li&gt;
&lt;/ol&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%2Fz5y4ywoa12fx934hs3mk.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%2Fz5y4ywoa12fx934hs3mk.png" alt="virtuat network seach" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;3. Select + Create and complete the configuration of the app-vnet. This virtual network requires two subnets, frontend and backend.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property            Value
Resource group           RG1
Virtual network name     app-vnet
Region                   West US 3
IPv4 address space   10.1.0.0/16
Subnet name          frontend
Subnet address range     10.1.0.0/24
Subnet name          backend
Subnet address range     10.1.1.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note:Leave all other settings as their defaults. When finished select “Review + create and then Create.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Inside each virtual network, you carve out subnets:&lt;br&gt;
_In app-vnet:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontend-subnet: for web servers that handle user traffic.&lt;/li&gt;
&lt;li&gt;backend-subnet: for database servers that store and process data.&lt;/li&gt;
&lt;li&gt;In hub-vnet:
&lt;em&gt;firewall-subnet: for deploying Azure Firewall or other security appliances.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Why its important:&lt;br&gt;
Subnets help organize resources and apply security rules. For example, you can restrict access so only the frontend talks to the backend, and all traffic flows through the firewall.&lt;/p&gt;
&lt;/blockquote&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%2Fuzhoyv8k9n6sjuuc63xk.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%2Fuzhoyv8k9n6sjuuc63xk.png" alt="Basic" width="800" height="372"&gt;&lt;/a&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%2F7tnur0bn0j0aa3c284bu.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%2F7tnur0bn0j0aa3c284bu.png" alt="frontsubnet" width="800" height="368"&gt;&lt;/a&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%2Fm4gc386frz01nf66onlm.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%2Fm4gc386frz01nf66onlm.png" alt="Backsubnet" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Create the Hub-vnet virtual network configuration. This virtual network has the firewall subnet.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property           Value
Resource group         RG1
Name                   hub-vnet
Region                 West US 3
IPv4 address space     10.0.0.0/16
Subnet name        AzureFirewallSubnet
Subnet address range   10.0.0.0/26
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvi7xk0h87fy5y3mcr893.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%2Fvi7xk0h87fy5y3mcr893.png" alt="hubvnet" width="800" height="364"&gt;&lt;/a&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%2F0mg5izipcynkr3e8otig.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%2F0mg5izipcynkr3e8otig.png" alt="hub" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5. Once the deployments are complete, search for and select your ‘virtual networks`.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;6. Verify your virtual networks and subnets were deployed.&lt;/em&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%2F09djn38w4w06wm4lfpmg.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%2F09djn38w4w06wm4lfpmg.png" alt="Vnetwork" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: we created two separate virtual networks:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;app-vnet: where your application lives.&lt;/li&gt;
&lt;li&gt;hub-vnet: where shared services like firewalls or VPN gateways reside.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;br&gt;
This separation allows you to centralize security and routing in the hub, while keeping application workloads isolated in the spoke. It’s scalable, secure, and mirrors enterprise-grade architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure Virtual Network Peering
&lt;/h2&gt;

&lt;p&gt;Virtual network peering enables you to seamlessly connect two or more Virtual Networks in Azure. SO the the virtual network peering between app-vnet and hub-vnet allows them to communicate privately over Azure’s backbone network.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for and select the app-vnet virtual network.&lt;/li&gt;
&lt;li&gt;In the Settings blade, select Peerings.&lt;/li&gt;
&lt;li&gt;+ Add a peering between the two virtual networks.&lt;/li&gt;
&lt;/ol&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%2Fwaj2fazimzmtpvm3zsg2.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%2Fwaj2fazimzmtpvm3zsg2.png" alt="add peering" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Property                              &lt;strong&gt;Value&lt;/strong&gt;&lt;br&gt;
Remote peering link name              &lt;strong&gt;app-vnet-to-hub&lt;/strong&gt;&lt;br&gt;
Virtual network                               &lt;strong&gt;hub-vnet&lt;/strong&gt;&lt;br&gt;
Local virtual network peering link name       &lt;strong&gt;hub-to-app-vnet&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note: Leave all other settings as their defaults. Select “Add” to create the virtual network peering.&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%2Fw1biz7epbogheizgjw7l.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%2Fw1biz7epbogheizgjw7l.png" alt="peering" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Once the deployment completes, verify the Peering status is Connected.&lt;/em&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%2Fqfncn9syia3gzc7syuuh.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%2Fqfncn9syia3gzc7syuuh.png" alt="connected" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters:&lt;/strong&gt;&lt;br&gt;
Peering avoids the need for public IPs or VPNs. It’s fast, secure, and cost-effective. You can control traffic flow and even route it through the firewall in the hub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;br&gt;
Congratulations on completing the exercise. Here are the main takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure virtual networks (VNets) provide a secure and isolated network environment for your cloud resources. You can create multiple virtual networks per region per subscription.&lt;/li&gt;
&lt;li&gt;When designing virtual networks make sure the VNet address space (CIDR block) doesn’t overlap with your organization’s other network ranges.&lt;/li&gt;
&lt;li&gt;A subnet is a range of IP addresses in the VNet. You can segment VNets into different size subnets, creating as many subnets as you require for organization and security within the subscription limit. Each subnet must have a unique address range.&lt;/li&gt;
&lt;li&gt;Certain Azure services, such as Azure Firewall, require their own subnet.&lt;/li&gt;
&lt;li&gt;Virtual network peering enables you to seamlessly connect two Azure virtual networks. The virtual networks appear as one for connectivity purposes.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>skillsch</category>
      <category>mslearn</category>
      <category>cloud</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Git &amp; GitHub — Step-by-Step: Push Your Resume from Local to GitHub</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Tue, 09 Sep 2025 14:23:44 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/git-github-step-by-step-push-your-resume-from-local-to-github-554d</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/git-github-step-by-step-push-your-resume-from-local-to-github-554d</guid>
      <description>&lt;p&gt;This walkthrough is designed to gently introduce you to the basics of Git and GitHub, using clear, step-by-step instructions. You’ll learn how to push a resume from your computer to a brand-new GitHub repository, using Git Bash across Windows, macOS, or Linux. We’ll stick with HTTPS for simplicity, but if you're curious, there's an optional section on SSH too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why bother?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Putting your resume on GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows tech-savvy professionalism.&lt;/li&gt;
&lt;li&gt;Creates a versioned, shareable copy (PDF or Markdown).&lt;/li&gt;
&lt;li&gt;Makes it easy to update and link in job applications or your portfolio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub account (github.com)&lt;/li&gt;
&lt;li&gt;Git installed (Git Bash on Windows): &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;https://git-scm.com/downloads&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A resume file ready (PDF, DOCX, or a Markdown README.md)&lt;/li&gt;
&lt;li&gt;Basic comfort with the terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;1. Install &amp;amp; configure Git (one-time)&lt;/em&gt;&lt;br&gt;
Open Git Bash and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# set your identity (replace with your real name &amp;amp; email)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# (optional) set helpful defaults
git config --global core.autocrlf input    # mac/linux; for Windows use true
git config --global init.defaultBranch main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Commits include author info. init.defaultBranch main makes new repos use main (GitHub default).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Create a local folder for your resume project&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;# make a folder and file and move into it
mkdir resume
cd resume

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

&lt;/div&gt;



&lt;p&gt;Place your resume file in that file with Vim command as show in the screenshot. Example filenames: Isaiah_Izibili_Resume.pdf&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%2Ftbq7yfkwzrdt9sppka36.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%2Ftbq7yfkwzrdt9sppka36.png" alt="file" width="800" height="550"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will help us to edit our CV in the Vi index.html file.( we need to use the following steps to edit:&lt;br&gt;
&lt;em&gt;1. click Esc on the keyboard to escape the insert mode disappears&lt;/em&gt;&lt;br&gt;
&lt;em&gt;2. click on Shift and column. it moves the consul under the page&lt;/em&gt;&lt;br&gt;
&lt;em&gt;3. then type :wq and enter(note w is to save while q is to escape back to the coding areas.&lt;/em&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%2Fytlyac17zul35v9iliaj.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%2Fytlyac17zul35v9iliaj.png" alt="index file" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Initialize a local Git repository&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;git init

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

&lt;/div&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%2Fm2upf4u07cy0l9qvi3wr.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%2Fm2upf4u07cy0l9qvi3wr.png" alt="git init" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the repo status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see if the file is added&lt;br&gt;
&lt;strong&gt;4) Add files and make your first commit&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;# add files to staging area
git add index.html(this should be the url from the created repository)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F91ifp5gnh50rv6rp12y2.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%2F91ifp5gnh50rv6rp12y2.png" alt="git add" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5) Create a GitHub repository (via the website)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to github.com and log in.&lt;/li&gt;
&lt;li&gt;Click New repository (or + → New repository).&lt;/li&gt;
&lt;li&gt;Name it (e.g., resume or isaiah-resume).&lt;/li&gt;
&lt;li&gt;Do not initialize with a README (if you have already done one locally).&lt;/li&gt;
&lt;li&gt;Click Create repository.
You’ll be shown the repo’s remote URL. Use the HTTPS one (e.g., &lt;a href="https://github.com/your-username/resume.git" rel="noopener noreferrer"&gt;https://github.com/your-username/resume.git&lt;/a&gt;) unless you set up SSH.&lt;/li&gt;
&lt;/ol&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%2F055od80ic6jccs8csxei.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%2F055od80ic6jccs8csxei.png" alt="repository" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) Link the local repo to GitHub (add remote)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add origin https://github.com/your-username/resume.git
Replace the URL below with the one GitHub gave you:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7) Make sure your main branch is named main (or use master if you prefer)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# force local branch name to main (safe even if already main)
git branch -M main

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

&lt;/div&gt;



&lt;p&gt;8) Push to GitHub&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# push and set upstream, first push
git push -u origin main

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

&lt;/div&gt;



&lt;p&gt;9) Verify on GitHub&lt;/p&gt;

&lt;p&gt;Open your repo URL in a browser — you should see README.md and your resume file. Click the resume to preview or download.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>skillch</category>
      <category>tutorial</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Deploy and configure Azure Monitor</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Wed, 03 Sep 2025 17:23:38 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/deploy-and-configure-azure-monitor-22do</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/deploy-and-configure-azure-monitor-22do</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today’s dynamic cloud environments, ensuring system health, performance, and security is critical for delivering seamless digital experiences. Azure Monitor provides a powerful, centralized platform for collecting, analyzing, and acting on telemetry data from applications, infrastructure, and network resources. By deploying and configuring Azure Monitor alongside Log Analytics, organizations can gain deep visibility into their cloud ecosystem, identify trends, and quickly address issues before they impact users.&lt;/p&gt;

&lt;p&gt;This article provides a step-by-step guide to deploying and configuring Azure Monitor, setting up Log Analytics, monitoring web applications, tracking compute and networking services, and creating custom alerts. Whether you’re an IT administrator, DevOps engineer, or cloud enthusiast, these practices will help you implement a proactive monitoring strategy that supports business continuity and operational efficiency.&lt;/p&gt;

&lt;p&gt;In this project, you’ll explore how to configure monitoring for workloads and infrastructure services using Azure Monitor. This article blends learning with hands-on practice, equipping you with practical skills to strengthen your cloud monitoring strategy.&lt;/p&gt;

&lt;p&gt;By the end, you’ll be confident in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying and configuring Log Analytics to centralize and analyze logs.&lt;/li&gt;
&lt;li&gt;Configuring monitoring for web applications to ensure performance and availability.&lt;/li&gt;
&lt;li&gt;Monitoring compute and networking services for health, traffic, and resource optimization.&lt;/li&gt;
&lt;li&gt;Configuring alerts to respond quickly to potential issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Prepare your Azure environment
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prepare your bring-your-own-subscription (BYOS)&lt;/strong&gt;&lt;br&gt;
This set of lab exercises assumes that you have global administrator permissions to an Azure subscription.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Resource Groups and select Resource groups from the list of results.&lt;/li&gt;
&lt;li&gt;On the Resource Groups page, select Create.&lt;/li&gt;
&lt;li&gt;On the Create a Resource Group page, select your subscription and enter the name rg-alpha. Set the region to East US, choose Review + Create, and then choose Create.&lt;/li&gt;
&lt;/ol&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%2Fcayxzqztevimwoewgkit.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%2Fcayxzqztevimwoewgkit.png" alt="Resourse Group" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[!NOTE] This set of exercises assumes that you choose to deploy in the East US Region, but you can change this to another region if you choose. Just remember that each time you see East US mentioned in these instructions you will need to substitute the region you have chosen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Create App Log Examiners security group&lt;/strong&gt;&lt;br&gt;
In this exercise, you create an Entra ID security group.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Azure Active Directory (or Entra ID) from the list of results.&lt;/li&gt;
&lt;li&gt;On the Default Directory page, select Groups.&lt;/li&gt;
&lt;/ol&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%2F7v05r1xajedvacpkqni0.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%2F7v05r1xajedvacpkqni0.png" alt="Select Group" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3.  On the Groups page, choose New Group.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;4.  On the New Group page, provide the values in the following table and choose Create.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Property  :   Value&lt;br&gt;
Group type    :  Security&lt;br&gt;
Group name    :   App Log Examiners&lt;br&gt;
Group description : App Log Examiners&lt;/p&gt;
&lt;/blockquote&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%2Fs3hef9ukvnspkdihs29a.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%2Fs3hef9ukvnspkdihs29a.png" alt="New Azure Active Directory" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy and configure WS-VM1&lt;/strong&gt;&lt;br&gt;
In this exercise, you deploy and configure a Windows Server virtual machine.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Virtual Machines and select Virtual Machines from the list of results.&lt;/li&gt;
&lt;li&gt;On the Virtual Machines page, choose Create and select Azure Virtual Machine.&lt;/li&gt;
&lt;/ol&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%2Flx3ajv7la8l8tzh0wgxd.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%2Flx3ajv7la8l8tzh0wgxd.png" alt="Virtual MAchine" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. On the Basics page of the Create A Virtual Machine wizard, select the following settings and then choose Review + Create.&lt;/em&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%2Fwvcjd1r0yz0zoht4zgkz.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%2Fwvcjd1r0yz0zoht4zgkz.png" alt="Table1" width="800" height="602"&gt;&lt;/a&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%2Fwtu94c986g63uxg29fq3.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%2Fwtu94c986g63uxg29fq3.png" alt="VM1 Basic" width="800" height="385"&gt;&lt;/a&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%2Fp1op4gnaas1dmxwdzygo.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%2Fp1op4gnaas1dmxwdzygo.png" alt="Basic2" width="800" height="602"&gt;&lt;/a&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%2F5v58fyrynv21k5lmg27d.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%2F5v58fyrynv21k5lmg27d.png" alt="Basic3" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Review the settings and select Create.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;5. Wait for the deployment to complete. Once deployment completes choose Go to resource.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;6. On the WS-VM1 properties page, choose Networking.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;7. On the Networking page, select the RDP rule.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;8. On the RDP rule space, change the Source to My IP address and choose Save.&lt;/em&gt;&lt;br&gt;
This restricts incoming RDP connections to the IP address you’re currently using.&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%2Fotewkptt1ohf3798kd7k.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%2Fotewkptt1ohf3798kd7k.png" alt="RDP1" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;9. On the Networking page, choose Add inbound port rule.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;10. On the Add inbound security rule page, configure the following settings and choose Add.&lt;/em&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%2F5zqdtm1ddyq339c6wc71.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%2F5zqdtm1ddyq339c6wc71.png" alt="inbound rule" width="800" height="358"&gt;&lt;/a&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%2Fr40pk3okk8vba74vxo1i.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%2Fr40pk3okk8vba74vxo1i.png" alt="Inbound rule 1" width="800" height="387"&gt;&lt;/a&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%2F932nfq1qksbvumt2s9ff.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%2F932nfq1qksbvumt2s9ff.png" alt="inbound rule security" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;11. On the WS-VM1 page, choose Connect.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;12. Under Native RDP, choose Select.&lt;/em&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%2F1m5q1f3gpy3flzijbm7o.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%2F1m5q1f3gpy3flzijbm7o.png" alt="Native RDP" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;13. On the Native RDP page, choose Download RDP file and then open the file.&lt;/em&gt; &lt;br&gt;
Opening the RDP file opens the Remote Desktop Connection dialog box.&lt;br&gt;
&lt;em&gt;14. On the Windows Security dialog box, choose More Choices and then choose Use a different account.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;15. Enter the username as .\prime and the password as the secure password you chose in Step 3, and choose OK.&lt;/em&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%2Fjcdo6uecmz1k08l291j2.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%2Fjcdo6uecmz1k08l291j2.png" alt="Username1" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;16. When signed into the Windows Server virtual machine, right-click on the Start hint and then choose Windows PowerShell (Admin).&lt;/em&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%2Fn565kw3motomtaehloi7.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%2Fn565kw3motomtaehloi7.png" alt="powershell" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;17. At the elevated command prompt, type the following command and press Enter. Install-WindowsFeature Web-Server -IncludeAllSubFeature -IncludeManagementTools&lt;/em&gt;&lt;br&gt;
&lt;em&gt;18. When the installation completes run the following command to change to the web server root directory. cd c:\inetpub\wwwroot_&lt;br&gt;
_19. Run the following command. Wget &lt;a href="https://raw.githubusercontent.com/Azure-Samples/html-docs-hello-world/master/index.html" rel="noopener noreferrer"&gt;https://raw.githubusercontent.com/Azure-Samples/html-docs-hello-world/master/index.html&lt;/a&gt; -OutFile index.html&lt;/em&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%2Fmidfduosj17edks62ztw.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%2Fmidfduosj17edks62ztw.png" alt="Installation" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy and configure LX-VM2&lt;/strong&gt;&lt;br&gt;
In this exercise you deploy and configure a Linux virtual machine.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Virtual Machines and select Virtual Machines from the list of results.&lt;/li&gt;
&lt;li&gt;On the Virtual Machines page, choose Create and select Azure Virtual Machine.&lt;/li&gt;
&lt;/ol&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%2Ffolddtd644n8mqhy46dt.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%2Ffolddtd644n8mqhy46dt.png" alt="Linux Vm" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. On the Basics page of the Create A Virtual Machine wizard, select the following settings and then choose Review + Create.&lt;/em&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%2Fj4twoqje5s63nrvcq9wr.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%2Fj4twoqje5s63nrvcq9wr.png" alt="form3" width="800" height="693"&gt;&lt;/a&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%2F534l71fbjkjehe2t1ius.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%2F534l71fbjkjehe2t1ius.png" alt="Linux2" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Review the information and choose Create.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;5. After the VM deploys, open the VM properties page and choose Extensions + Applications under Settings.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;6. Choose Add and select the Network Watcher Agent for Linux. Choose Next and then choose Review and Create. Choose Create.&lt;/em&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%2Fdomb5js6j3fpbxspjj24.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%2Fdomb5js6j3fpbxspjj24.png" alt="Network watcher" width="800" height="385"&gt;&lt;/a&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%2Fy9int3dv4wvvktkgr8pi.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%2Fy9int3dv4wvvktkgr8pi.png" alt="Network washer" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;7. Configure the AzureNetworkWatcherExtension and the OmsAgentForLinux extension so that they automatically upgrade.&lt;/em&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%2Fyp70i9psvzmm5be8pmyc.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%2Fyp70i9psvzmm5be8pmyc.png" alt="atcher2" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy a web app with an SQL Database&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure that you’re signed into the Azure Portal.&lt;/li&gt;
&lt;li&gt;In your browser, open a new browser tab and navigate to &lt;a href="https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.web/web-app-sql-database" rel="noopener noreferrer"&gt;https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.web/web-app-sql-database&lt;/a&gt;
&lt;em&gt;3. On the GitHub page, choose Deploy to Azure.&lt;/em&gt;
&lt;em&gt;4. A new tab opens. If necessary, re-sign into Azure with the account that has Global Administrator privileges.&lt;/em&gt;
&lt;em&gt;5. On the Basics page, select Edit template.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&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%2F7gtufs36hp6mn9pmn4jl.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%2F7gtufs36hp6mn9pmn4jl.png" alt="Edith template" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the template editor, delete the contents of lines 158 to 174 inclusive and delete the “,” on line 157. Choose Save.&lt;/li&gt;
&lt;/ol&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%2Fipbrjckbccckxqlfe68u.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%2Fipbrjckbccckxqlfe68u.png" alt="save template" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Basics page, provide the following information and choose Next.&lt;/li&gt;
&lt;/ol&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%2Fw5zeym1tqqvorutc3epc.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%2Fw5zeym1tqqvorutc3epc.png" alt="Basic page" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;8. Review the information presented and select Create.&lt;/em&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%2Fjrzmkrr6nnfgll40cjwf.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%2Fjrzmkrr6nnfgll40cjwf.png" alt="Review and create" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;9. After the deployment completes, choose Go to resource group.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy a Linux web app&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure that you’re signed into the Azure Portal.&lt;/li&gt;
&lt;li&gt;In your browser, open a new browser tab and navigate to &lt;a href="https://learn.microsoft.com/en-us/samples/azure/azure-quickstart-templates/webapp-basic-linux/" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/samples/azure/azure-quickstart-templates/webapp-basic-linux/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the GitHub page, choose &lt;strong&gt;Deploy to Azure&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2Fa6zn85xqa6iikfp407u0.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%2Fa6zn85xqa6iikfp407u0.png" alt="Deploy" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the &lt;strong&gt;Basics page&lt;/strong&gt;, provide the following information and choose &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2Fzolm7qwa0d73aasnzxu0.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%2Fzolm7qwa0d73aasnzxu0.png" alt="Basic 4" width="800" height="272"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;5. Review the information and choose Create.&lt;/em&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%2Fu5df6qclt230glgrqocb.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%2Fu5df6qclt230glgrqocb.png" alt="Review and Create" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2.Deploy Log Analytics
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Task 1: Create a Log Analytics workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter &lt;strong&gt;Log Analytics&lt;/strong&gt; and select &lt;strong&gt;Log Analytics workspaces&lt;/strong&gt; from the list of results.&lt;/li&gt;
&lt;/ol&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%2Fdfuywm2i3k1wq9xpp3sv.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%2Fdfuywm2i3k1wq9xpp3sv.png" alt="Log Analytics Workspace" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Log Analytics workspaces page, choose &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Basics&lt;/strong&gt; page of the Create Log Analytics workspace wizard, provide the following information and choose &lt;strong&gt;Review + Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2F7tqowvc8dszbq7agnu90.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%2F7tqowvc8dszbq7agnu90.png" alt="Form5" width="783" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Review the information and choose Create.&lt;/em&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%2Fig6mnszpi57079wcbd1e.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%2Fig6mnszpi57079wcbd1e.png" alt="Log workspace" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task2: Configure Log Analytics data retention and archive policies&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Log Analytics and select Log Analytics workspaces from the list of results.&lt;/li&gt;
&lt;li&gt;On the Log Analytics workspaces page, choose LogAnalytics1.&lt;/li&gt;
&lt;li&gt;On the Log Analytics workspace page for LogAnalytics1, choose Usage and estimated costs.&lt;/li&gt;
&lt;li&gt;Select Data Retention and set the slider to 60 days. Choose OK.&lt;/li&gt;
&lt;/ol&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%2F8geo4x8hy5e50ibw85so.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%2F8geo4x8hy5e50ibw85so.png" alt="Log Analytics" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Log Analytics workspace page for LogAnalytics1, choose Usage and estimated costs.&lt;/li&gt;
&lt;li&gt;Select Daily cap. Choose On. Set the daily cap to 10 GB and choose OK.&lt;/li&gt;
&lt;/ol&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%2Ft4oci9y3d1orprohkz12.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%2Ft4oci9y3d1orprohkz12.png" alt="Daily Cap" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task3: Enable access to a Log Analytics workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Log Analytics and select Log Analytics workspaces from the list of results.&lt;/li&gt;
&lt;li&gt;On the Log Analytics workspaces page, choose LogAnalytics1.&lt;/li&gt;
&lt;li&gt;Select Access control (IAM).&lt;/li&gt;
&lt;/ol&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%2F7iw6ijd2ts0vddp3yzgr.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%2F7iw6ijd2ts0vddp3yzgr.png" alt="add role" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose Add and then choose Add role assignment.&lt;/li&gt;
&lt;li&gt;On the list of roles, select Log Analytics Reader and choose Next.&lt;/li&gt;
&lt;/ol&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%2Fh6cke9z17k1yodhkdivf.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%2Fh6cke9z17k1yodhkdivf.png" alt="Reader" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Members page, choose Select Members and choose the App Log Examiners security group. Choose Select.&lt;/li&gt;
&lt;li&gt;On the Members space, choose Review + Assign.&lt;/li&gt;
&lt;/ol&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%2Fyb8w118sa34pdh2tc6f4.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%2Fyb8w118sa34pdh2tc6f4.png" alt="add member" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Monitor web apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task1: Enable Application Insights&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose App Services for the Web App with an SQL Database.&lt;/li&gt;
&lt;li&gt;Under Settings choose Application Insights.&lt;/li&gt;
&lt;li&gt;On the Application Insights page, choose Turn On Application Insights.&lt;/li&gt;
&lt;/ol&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%2Fpnchww8c5akevw736hzc.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%2Fpnchww8c5akevw736hzc.png" alt="Insight1" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Application Insights page, ensure that Create a new resource is selected and that the Log Analytics Workspace is set to LogAnalytics1 and choose Apply.&lt;/li&gt;
&lt;/ol&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%2Fniqtoz4dnrfk903ewaow.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%2Fniqtoz4dnrfk903ewaow.png" alt="application insight" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Apply monitoring settings dialog, choose Yes.&lt;/li&gt;
&lt;/ol&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%2F6615s5530oljnjs7og4n.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%2F6615s5530oljnjs7og4n.png" alt="apply monitor" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tast2: Disable logging for .NET core snapshot debugger&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose App Services for the Web App with an SQL Database.&lt;/li&gt;
&lt;li&gt;Under Settings choose Application Insights.&lt;/li&gt;
&lt;/ol&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%2Fp8e6qxg0557gsf0amiey.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%2Fp8e6qxg0557gsf0amiey.png" alt="Insights3" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under Instrument your application, choose .NET Core and then set the Snapshot Debugger setting to Off. Choose Apply.&lt;/li&gt;
&lt;/ol&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%2Fr3kyi47h50itscn7r4ll.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%2Fr3kyi47h50itscn7r4ll.png" alt="NETcore" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Apply Monitoring Settings dialog box, choose Yes.&lt;/li&gt;
&lt;/ol&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%2Fvptkdwbrni6h8o77d879.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%2Fvptkdwbrni6h8o77d879.png" alt="appservice" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task3: Configure web app HTTP logs to be written to a Log Analytics workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose App Services for the Web App with an SQL Database.&lt;/li&gt;
&lt;li&gt;Under Monitoring, choose Diagnostic settings.&lt;/li&gt;
&lt;/ol&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%2Fculqb9ezog1tnwz5e7nl.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%2Fculqb9ezog1tnwz5e7nl.png" alt="Diagnostic set1" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Diagnostic settings page, select + Add diagnostic settings.&lt;/li&gt;
&lt;li&gt;On the Diagnostic settings page, choose the following and select Save.&lt;/li&gt;
&lt;/ol&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%2F53eiae2nty2ljmx61w87.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%2F53eiae2nty2ljmx61w87.png" alt="form5" width="800" height="281"&gt;&lt;/a&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%2Famso1bfg1f2jkvouyl9d.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%2Famso1bfg1f2jkvouyl9d.png" alt="Diagnostic" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task4: Configure SQL Insights data to be written to a Log Analytics workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose the sample SQL database.&lt;/li&gt;
&lt;li&gt;Under Monitoring, choose Diagnostic settings.&lt;/li&gt;
&lt;/ol&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%2Fbenkijoollbvh4k3lmlk.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%2Fbenkijoollbvh4k3lmlk.png" alt="diag4" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Diagnostic settings page, choose Add diagnostic setting.&lt;/li&gt;
&lt;li&gt;On the Diagnostic setting page, provide the following information and choose Save.&lt;/li&gt;
&lt;/ol&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%2Fio4cm6jzjdfhu51a2t2g.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%2Fio4cm6jzjdfhu51a2t2g.png" alt="form6" width="793" height="316"&gt;&lt;/a&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%2F72gqzp00lkzkzquzgmak.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%2F72gqzp00lkzkzquzgmak.png" alt="informa Insight3" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task5: Enable file and configuration change tracking for web apps&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose the AzureLinuxAppWXYZ-webapp.&lt;/li&gt;
&lt;li&gt;Choose Diagnose and Solve Problems.&lt;/li&gt;
&lt;li&gt;In the search dialog box, type Application Changes.&lt;/li&gt;
&lt;/ol&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%2F0f5di5477jnm1gcfxmxa.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%2F0f5di5477jnm1gcfxmxa.png" alt="Application change" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Change Analysis page, choose Configure.&lt;/li&gt;
&lt;li&gt;On the Enable file and configuration change tracking page, change the Status slider to On and then choose Save.&lt;/li&gt;
&lt;/ol&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%2Flxlw9inkdjk9pvzwipjf.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%2Flxlw9inkdjk9pvzwipjf.png" alt="Configure" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Configure monitoring for compute services
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Task1: Create a data collection endpoint&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Monitor and select Monitor from the list of results.&lt;/li&gt;
&lt;li&gt;In the Monitor page, under Settings, choose Data Collection Endpoints.&lt;/li&gt;
&lt;li&gt;On the Data Collection Endpoints page, choose Create.&lt;/li&gt;
&lt;/ol&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%2F4ya9lfd5jxm0zx9c6pp3.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%2F4ya9lfd5jxm0zx9c6pp3.png" alt="Data collotion" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Create Data Collection Endpoint page, provide the following settings and then choose Review + Create.&lt;/li&gt;
&lt;li&gt;Review the settings and choose Create.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;![form8](&lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d37gnt4gsx0onei68yq5.png" rel="noopener noreferrer"&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d37gnt4gsx0onei68yq5.png&lt;/a&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%2Fxtdmvactzx0uhasrykji.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%2Fxtdmvactzx0uhasrykji.png" alt="Mornitor" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 2: Create a data collection rule&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Monitor and select Monitor from the list of results.&lt;/li&gt;
&lt;li&gt;In the Monitor page, under Settings, choose Data Collection Rules.&lt;/li&gt;
&lt;li&gt;On the Data Collection Rules page, choose Create.&lt;/li&gt;
&lt;/ol&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%2Fply0n2s3s2zwaxrnwmur.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%2Fply0n2s3s2zwaxrnwmur.png" alt="Create rules" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Create Data Collection Rule page, configure the following settings and choose Next.&lt;/li&gt;
&lt;/ol&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%2F4nxtdqqcup5a371q7q5w.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%2F4nxtdqqcup5a371q7q5w.png" alt="Forms7" width="800" height="286"&gt;&lt;/a&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%2Fa21910topx5mrenz3vzg.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%2Fa21910topx5mrenz3vzg.png" alt="Basic Resources" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Resources page, choose Add Resources.&lt;/li&gt;
&lt;/ol&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%2Fy5lmv4pc46c330jt9cjc.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%2Fy5lmv4pc46c330jt9cjc.png" alt="Add resources" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Select a scope page, enable the WS-VM1 checkbox and choose Apply.&lt;/li&gt;
&lt;/ol&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%2Foejoi7fwsjvx34i0shs9.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%2Foejoi7fwsjvx34i0shs9.png" alt="VM1" width="800" height="385"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;7. On the Create Data Collection Rule page, choose Next.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;8. On the Collect and Deliver page, choose Add data source.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;9. On the Add data source page, select Windows Event Logs. In the Application category enable the Critical and Error categories. In the Security category, choose the Audit Failure category. In the System category, enable the Critical and Error categories.&lt;/em&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%2F8ey5msbixpkualqr7pjs.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%2F8ey5msbixpkualqr7pjs.png" alt="Collection Rule" width="800" height="371"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;10. Choose Next.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;11. On the Destination page, configure the following settings:&lt;/em&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%2Fy9xv553mk20hc37xjnbe.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%2Fy9xv553mk20hc37xjnbe.png" alt="Form0" width="786" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;12. Choose Add data source.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;13. Choose Review + Create and then choose Create.&lt;/em&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%2Fyj7bmb08ca4pexgardf8.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%2Fyj7bmb08ca4pexgardf8.png" alt="destination2" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task3: Add an IIS log collection to an existing data collection rule&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Monitor and select Monitor from the list of results.&lt;/li&gt;
&lt;li&gt;In the Monitor page, under Settings, choose Data Collection Rules.&lt;/li&gt;
&lt;li&gt;Choose the WinVMDRC rule in rg-alpha.&lt;/li&gt;
&lt;/ol&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%2Fabvhld7m9bxc7csb1jdx.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%2Fabvhld7m9bxc7csb1jdx.png" alt="WinVM" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under Configuration, choose Data Sources.&lt;/li&gt;
&lt;li&gt;On the Data Sources page, choose Add.&lt;/li&gt;
&lt;li&gt;On the Add Data Source page, select IIS Logs.&lt;/li&gt;
&lt;li&gt;Choose Next.&lt;/li&gt;
&lt;/ol&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%2Fd4xmx53xojcsqs8naq6e.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%2Fd4xmx53xojcsqs8naq6e.png" alt="IIS logs" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Destination page, configure the following settings:&lt;/li&gt;
&lt;/ol&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%2Fawe18thcall1fbhdds8t.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%2Fawe18thcall1fbhdds8t.png" alt="rule2" width="800" height="178"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;9. Choose Add data source.&lt;/em&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%2Ftvyma9d7hvj4jkj2g4ya.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%2Ftvyma9d7hvj4jkj2g4ya.png" alt="Add source" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task4: Configure Network Connection Monitor for a Linux IaaS virtual machine&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Network Watcher and select Network Watcher from the list of results.&lt;/li&gt;
&lt;/ol&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%2Fwnelzoxgih82bng3lvi1.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%2Fwnelzoxgih82bng3lvi1.png" alt="Network wahcer" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under Monitoring, choose Connection Monitor.&lt;/li&gt;
&lt;li&gt;On the Connection Monitor page, choose Create.&lt;/li&gt;
&lt;li&gt;On the Basics page of the Create Connection Monitor wizard, provide the following information and choose Next.&lt;/li&gt;
&lt;/ol&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%2F3gdv2vzupgsgyarj2rh2.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%2F3gdv2vzupgsgyarj2rh2.png" alt="Form12" width="800" height="214"&gt;&lt;/a&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%2F7drspztco96d0deqzax8.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%2F7drspztco96d0deqzax8.png" alt="Basic21" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5. On the Add test group details page, enter the name LinuxIPTest and choose Add sources.&lt;/em&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%2Fd0o80cm1w579jy0bfw3d.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%2Fd0o80cm1w579jy0bfw3d.png" alt="LinuxIP Test" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;6. On the Add Sources page, select Azure Endpoints and set the type to Virtual machines. Select Subnet and then enable the Linux-VM checkbox. Choose Add Endpoints.&lt;/em&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%2Fi5ifqe1egm9eti0j0qdp.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%2Fi5ifqe1egm9eti0j0qdp.png" alt="Azure Endpoint" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;7. Choose Add Test Configuration.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;8. On the Add Test Configuration page, enter the name DefaultHTTP and then choose Add Test Configuration.&lt;/em&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%2Fde1t9zyq9yru0v6l4ph3.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%2Fde1t9zyq9yru0v6l4ph3.png" alt="Test Configuration" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;9. Choose Add Destinations. Select Azure Endpoints and set the type to Virtual machines. Select Subnet and then enable the WS-VM1 checkbox. Select Add Endpoints.&lt;/em&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%2F8lf63gndbviljrvn3f78.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%2F8lf63gndbviljrvn3f78.png" alt="add Endpoint" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;10. Choose Add Test Group.&lt;/em&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%2Fdihecf3v07ngp2vu5l8b.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%2Fdihecf3v07ngp2vu5l8b.png" alt="Test Group" width="800" height="385"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;11. Choose Review and Create and then choose Create.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5 Configure alerts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Task1: Create an action group to send an email&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter Monitor and select Monitor from the list of results.&lt;/li&gt;
&lt;li&gt;Select Alerts in the navigation menu.&lt;/li&gt;
&lt;li&gt;Choose Action Groups.&lt;/li&gt;
&lt;/ol&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%2Ffpnzt6v5hq8w7x6wwdmv.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%2Ffpnzt6v5hq8w7x6wwdmv.png" alt="Action group" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. On the Action Groups page, choose Create.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;5. On the Basics page of the Create Action Group wizard, configure the following settings and choose Next.&lt;/em&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%2F8as1cgvy5wf3xtfgd9bt.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%2F8as1cgvy5wf3xtfgd9bt.png" alt="Table2" width="800" height="236"&gt;&lt;/a&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%2Foz31mb6ps6kt7llqcuvd.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%2Foz31mb6ps6kt7llqcuvd.png" alt=" " width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;6. On the Notifications page, set the notification type to Email/SMS message/Push/Voice and the Name to NotificationEmail. Choose the Edit (pencil) icon.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;7. On the Email/SMS message/Push/Voice enable the email checkbox and enter the address &lt;a href="mailto:prime@fabrikam.com"&gt;prime@fabrikam.com&lt;/a&gt;. Choose OK.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;8. Choose Review and Create. Choose Create.&lt;/em&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%2F0rzd8utf7kmg2e1of6lx.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%2F0rzd8utf7kmg2e1of6lx.png" alt="Review and create2" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task2: Create an alert for virtual machine CPU utilization&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure Portal Search Bar, enter rg-alpha and select rg-alpha from the list of results.&lt;/li&gt;
&lt;li&gt;From the list of items in the resource group, choose Linux-VM2.&lt;/li&gt;
&lt;li&gt;On the Linux-VM2 properties page, choose Alerts under Monitoring.&lt;/li&gt;
&lt;li&gt;On the Alerts page, choose Create and then choose Alert rule.&lt;/li&gt;
&lt;/ol&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%2F1fv694i1100a819epgm2.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%2F1fv694i1100a819epgm2.png" alt="Alert Rule4" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Condition page of the Create an Alert Rule wizard, set the Signal name to Percentage CPU. Use the default settings and choose Next.&lt;/li&gt;
&lt;/ol&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%2F2ue5eqfh6g0x3il58x05.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%2F2ue5eqfh6g0x3il58x05.png" alt="Percentage Usage" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Actions page, choose Select Action Group.&lt;/li&gt;
&lt;li&gt;On the Select Action Groups page, choose NotifyCPU and choose Select.&lt;/li&gt;
&lt;/ol&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%2Fv8mf7l1r93agbhzgarvi.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%2Fv8mf7l1r93agbhzgarvi.png" alt="Actiongroup6" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the Details page enter the Alert rule name HighCPU. Choose Review and Create and then choose Create.&lt;/li&gt;
&lt;/ol&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%2Fi4p519wn18zw2afp4tip.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%2Fi4p519wn18zw2afp4tip.png" alt="Revieand create" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Effective monitoring is a cornerstone of cloud success. By leveraging Azure Monitor’s integrated tools, IT teams can transform raw telemetry into actionable insights, ensuring that applications remain reliable, scalable, and secure. Configuring Log Analytics provides the foundation for deep analysis, while targeted monitoring of web apps, compute, and networking resources helps maintain optimal performance.&lt;/p&gt;

&lt;p&gt;Implementing well-defined alerts ensures rapid response to potential issues, reducing downtime and improving user experience. With this deployment strategy, organizations can shift from reactive troubleshooting to proactive optimization—unlocking the full potential of Microsoft Azure’s cloud ecosystem.&lt;/p&gt;

</description>
      <category>skillsch</category>
      <category>microsoft</category>
      <category>devops</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Step-by-Step Guide: From Virtual Machine to Scale Set in Azure Porta</title>
      <dc:creator>Isaiah Izibili</dc:creator>
      <pubDate>Wed, 20 Aug 2025 01:15:40 +0000</pubDate>
      <link>https://dev.to/isaiah_izibili_7a39b7d627/step-by-step-guide-from-virtual-machine-to-scale-set-in-azure-porta-3ee</link>
      <guid>https://dev.to/isaiah_izibili_7a39b7d627/step-by-step-guide-from-virtual-machine-to-scale-set-in-azure-porta-3ee</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Step 1: Create Your First Virtual Machine (VM)
&lt;/h2&gt;

&lt;p&gt;The journey begins with setting up a VM in the Azure Portal — think of it as building the foundation of your cloud house.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Sign in to Azure Portal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Head over to portal.azure.com and sign in with your Azure account.&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%2F1od8ialoslytzwx7vnz0.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%2F1od8ialoslytzwx7vnz0.png" alt="loginto azure" width="706" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Launch a New VM Wizard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the left-hand menu, click Create a resource.&lt;/p&gt;

&lt;p&gt;Under Compute, select Virtual Machine.&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%2Fcawlx3e1yxwjgp2lsn6f.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%2Fcawlx3e1yxwjgp2lsn6f.png" alt="lurnch VM machine" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. Configure the Basics&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s where you define the identity of your VM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subscription – Choose the subscription under which resources will be billed.&lt;/li&gt;
&lt;li&gt;Resource group – Group related resources for easy management (create new or reuse).&lt;/li&gt;
&lt;li&gt;VM Name &lt;/li&gt;
&lt;li&gt;Region – Select a region close to your users for lower latency.&lt;/li&gt;
&lt;/ul&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%2F8t5lm1fimj4scnft188r.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%2F8t5lm1fimj4scnft188r.png" alt="basic 1" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Availability options – Choose redundancy level (e.g., single zone, availability zone).&lt;/li&gt;
&lt;li&gt;Image – Pick your operating system (Windows Server, Ubuntu, etc.).&lt;/li&gt;
&lt;li&gt;Size – Select based on CPU/RAM needs.&lt;/li&gt;
&lt;/ul&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%2Ffj3ct0q05kdfbedpgizb.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%2Ffj3ct0q05kdfbedpgizb.png" alt="Basic 2" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication – Password or SSH key (SSH is more secure for Linux).&lt;/li&gt;
&lt;/ul&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%2Fp0uc3ayljz15gxeh2mrq.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%2Fp0uc3ayljz15gxeh2mrq.png" alt="Basic3" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Networking Setup&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default, Azure creates a new VNet and subnet.&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%2Fav4ah7il8r0j22zmjpgl.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%2Fav4ah7il8r0j22zmjpgl.png" alt="Network" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can customize if you already have a network design.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5. Management, Security, and Advanced Settings&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable auto-shutdown to save costs.&lt;/li&gt;
&lt;li&gt;Turn on boot diagnostics for easier troubleshooting.&lt;/li&gt;
&lt;/ul&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%2F7frby3uwntzu0idoe3n3.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%2F7frby3uwntzu0idoe3n3.png" alt="Autoshutdone" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;6. Review + Create&lt;/em&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%2Fmbmtmn0sfe52l67t2kvh.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%2Fmbmtmn0sfe52l67t2kvh.png" alt="Review and create" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Double-check everything, then click Create.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Azure will deploy your VM in a few minutes. 🎉&lt;/p&gt;
&lt;/blockquote&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%2Fvfr8h23kodsof2xttibs.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%2Fvfr8h23kodsof2xttibs.png" alt="VM Deployment complete" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💾 Step 2: Enhance the VM (Add Storage, Security &amp;amp; Monitoring)&lt;/p&gt;

&lt;p&gt;Now that your VM is alive, let’s give it more power and visibility.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Attach a Data Disk&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your VM → Disks → Add data disk.&lt;/li&gt;
&lt;li&gt;Specify size, name, and caching preferences.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Hit Save.&lt;/p&gt;
&lt;/blockquote&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%2F3dr30a0zlbi90rew3is7.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%2F3dr30a0zlbi90rew3is7.png" alt="Disk" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💡 Pro Tip: Keep OS disk for system files only. Store applications/data on attached data disks for better performance and scalability.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Configure Networking&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NSG Rules: Allow only required traffic (e.g., RDP 3389 for Windows, SSH 22 for Linux).&lt;/li&gt;
&lt;/ul&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%2Fpwig65onkth61f304nmq.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%2Fpwig65onkth61f304nmq.png" alt="Inboundrule" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VNet/Subnet: Ensure your VM lives in the right subnet for connectivity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;3. Enable Monitoring&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under Monitoring, turn on Azure Monitor / Log Analytics (via AMA + DCRs).&lt;/li&gt;
&lt;li&gt;This enables performance tracking and log collection for health insights.&lt;/li&gt;
&lt;/ul&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%2Fno1j5hylnkwacvjuhwie.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%2Fno1j5hylnkwacvjuhwie.png" alt="Enable insight" width="800" height="341"&gt;&lt;/a&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%2F328tb2m05z0v7g7g10jr.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%2F328tb2m05z0v7g7g10jr.png" alt="configure insight" width="800" height="341"&gt;&lt;/a&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%2Ffzwlgl6bviwa73atfjf7.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%2Ffzwlgl6bviwa73atfjf7.png" alt=" " width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Install Software and Extensions&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Connect to your VM (RDP/SSH).&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%2Fqxis2xqbh5lz5d1t6wh3.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%2Fqxis2xqbh5lz5d1t6wh3.png" alt="connect" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install apps or use Extensions for automation (e.g., Custom Script Extension).&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼 Step 3: Capture Your VM as a Reusable Image
&lt;/h2&gt;

&lt;p&gt;Before scaling, you need a template image — this ensures all future VMs start with the same setup.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Prepare the VM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Install apps, apply patches, and configure settings.&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%2F20p174fy4d6aqo65se3x.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%2F20p174fy4d6aqo65se3x.png" alt="selectvm" width="800" height="365"&gt;&lt;/a&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%2Frh0a9k6hbfopy7l88el4.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%2Frh0a9k6hbfopy7l88el4.png" alt="vwselect" width="800" height="365"&gt;&lt;/a&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%2Fndppvtlgsqzxqk91v4tz.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%2Fndppvtlgsqzxqk91v4tz.png" alt="virtual machine" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remove temporary files, browser history, or unique identifiers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Generalize the VM (Windows)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RDP into VM → open Command Prompt (Admin).&lt;/li&gt;
&lt;/ul&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%2F6q1f6xqq3gmxijtalaxy.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%2F6q1f6xqq3gmxijtalaxy.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;br&gt;
Run:&lt;/p&gt;

&lt;p&gt;%windir%\system32\sysprep\sysprep.exe /oobe /generalize /shutdown /quiet&lt;/p&gt;

&lt;p&gt;⚠️ Note: /oobe ensures the VM boots into first-time setup mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Step 4: Build a Shared Image Gallery
&lt;/h2&gt;

&lt;p&gt;Think of this as your central library of VM images.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Create the Gallery&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Create a resource → Compute → Shared Image Gallery.&lt;/li&gt;
&lt;/ul&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%2F1q5e0xn0ukrpygx8x7e2.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%2F1q5e0xn0ukrpygx8x7e2.png" alt="image gallery" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter name, region, resource group → Create.&lt;/li&gt;
&lt;/ul&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%2Fuo7p87m2i1l733bp5d8f.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%2Fuo7p87m2i1l733bp5d8f.png" alt="created gallery" width="800" height="343"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;2. Add Image Version&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inside the gallery, click + Image Version.&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%2Fpvyj61w2xwc77vztre20.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%2Fpvyj61w2xwc77vztre20.png" alt="Image version" width="800" height="339"&gt;&lt;/a&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%2Ff7g3023zz731xxcmb80v.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%2Ff7g3023zz731xxcmb80v.png" alt="Image versioning" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the captured image as source.&lt;/p&gt;

&lt;p&gt;Define versioning (e.g., 1.0.0).&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%2Fxv8j443oyxc4tny28x2x.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%2Fxv8j443oyxc4tny28x2x.png" alt="image definition" width="800" height="357"&gt;&lt;/a&gt;&lt;br&gt;
Publish.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3. Capture the VM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Portal: VM → Operations → Capture.&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%2Fmi25xntk5z0qel6sjmgj.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%2Fmi25xntk5z0qel6sjmgj.png" alt="Image capture" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name your image.&lt;/li&gt;
&lt;li&gt;Choose “Yes” to delete VM after capture.&lt;/li&gt;
&lt;/ul&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%2Fw11xnzvrhneebk3k1cqb.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%2Fw11xnzvrhneebk3k1cqb.png" alt="Image creation" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select Create a managed image.&lt;/li&gt;
&lt;/ul&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%2Fs3trbscqqjpxfuikdpzk.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%2Fs3trbscqqjpxfuikdpzk.png" alt="Image created" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ Step 5: Deploy a Virtual Machine Scale Set (VMSS)
&lt;/h2&gt;

&lt;p&gt;VMSS = automatic scaling army of VMs built from your golden image.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Create VMSS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Portal → Create a resource → Compute → Virtual Machine Scale Set.&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%2Fbjkg53ent05mvefkilin.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%2Fbjkg53ent05mvefkilin.png" alt="create vmss" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Basic Settings&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick resource group, region, and name.&lt;/li&gt;
&lt;li&gt;For Image, select your Shared Image Gallery image.&lt;/li&gt;
&lt;/ul&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%2Fhg5swg7lzzzuqekgtlfd.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%2Fhg5swg7lzzzuqekgtlfd.png" alt="vmss basic" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose size and instance count.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;3. Networking&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Attach to existing VNet/Subnet.&lt;/p&gt;

&lt;p&gt;Add load balancer if traffic distribution is needed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4. Scaling&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Configure auto-scaling rules (CPU %, schedule-based).&lt;/p&gt;

&lt;p&gt;Review + Create.&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%2Fn7w6svb03a9ohayipqws.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%2Fn7w6svb03a9ohayipqws.png" alt="Review and create" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Step 6: Test Your Scale Set
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Scale Up → Increase instance count and watch Azure deploy new VMs.&lt;/li&gt;
&lt;/ul&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%2F9c222na736gzon313vfi.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%2F9c222na736gzon313vfi.png" alt="Scale up" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale Down → Reduce instances and see cost optimization in action.&lt;/li&gt;
&lt;/ul&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%2F3abb3np72r1hhow31znh.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%2F3abb3np72r1hhow31znh.png" alt="Scaledown" width="800" height="344"&gt;&lt;/a&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%2F4g5arau9wzrurxhxsq2r.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%2F4g5arau9wzrurxhxsq2r.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>skillsch</category>
      <category>devops</category>
      <category>cloudcomputing</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
