<?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: Kolarinde Awopetutimileyin</title>
    <description>The latest articles on DEV Community by Kolarinde Awopetutimileyin (@awokay).</description>
    <link>https://dev.to/awokay</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3717243%2F9c334bac-24e3-481f-81c7-36851988fa3a.jpg</url>
      <title>DEV Community: Kolarinde Awopetutimileyin</title>
      <link>https://dev.to/awokay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/awokay"/>
    <language>en</language>
    <item>
      <title>Containerizing a Full-Stack To-Do Application with Docker Compose (Node.js + MySQL)</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Fri, 07 Aug 2026 10:48:18 +0000</pubDate>
      <link>https://dev.to/awokay/containerizing-a-full-stack-to-do-application-with-docker-compose-nodejs-mysql-4jh1</link>
      <guid>https://dev.to/awokay/containerizing-a-full-stack-to-do-application-with-docker-compose-nodejs-mysql-4jh1</guid>
      <description>&lt;p&gt;&lt;strong&gt;A hands-on lab documenting the orchestration of a multi-container application using Docker Compose — from cloning source code to a live, database-backed web app.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;This lab covers the containerization and orchestration of a multi-service web application using Docker Compose. The project clones a real-world Node.js to-do list application backed by a MySQL database, defines both services declaratively in a single compose.yaml file, and brings the entire stack online with one command — demonstrating core DevOps skills in container orchestration, service networking, and persistent data management. Two real configuration errors were also encountered and resolved along the way, since debugging is as much a part of the DevOps process as the happy path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools &amp;amp; Technologies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker Desktop — container runtime and management UI&lt;/li&gt;
&lt;li&gt;Docker Compose — multi-container orchestration (compose.yaml)&lt;/li&gt;
&lt;li&gt;Node.js (node:22-alpine) — application server image&lt;/li&gt;
&lt;li&gt;MySQL 8.0 — relational database with a persistent named volume&lt;/li&gt;
&lt;li&gt;Git — cloning the application source from GitHub&lt;/li&gt;
&lt;li&gt;VS Code + PowerShell — local development and terminal environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;The compose.yaml file defines two services on a shared Docker network: an app service built from the node:22-alpine image and exposed on port 3000, and a mysql service running MySQL 8.0 with its data persisted to a named volume (todo-mysql-data) so records survive container restarts. Environment variables provision the database root password and create the todos database automatically on first boot, letting the entire stack start with a single docker compose up command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Walkthrough
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Clone the Application Source Code&lt;/strong&gt;&lt;br&gt;
Work began in a fresh DOCKER COMPOSE working directory inside VS Code. The first clone attempt used a malformed URL (missing the // after the protocol), which Git misread as an SSH host reference, producing a "Could not resolve hostname" error. Correcting the URL to a proper HTTPS format resolved the issue immediately.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6n1yx562g24xksva99xf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6n1yx562g24xksva99xf.png" alt=" " width="800" height="411"&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;git clone https://GitHub.com/dockersamples/todo-list-app   # failed — bad URL
git clone https://GitHub.com/dockersamples/todo-list-app   # corrected
cd todo-list-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Troubleshooting note: git clone requires a well-formed protocol (https://); a single missing slash caused Git to treat the URL as an SSH remote instead of HTTPS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Review the Docker Compose Configuration&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F37gjrja4scjv0pwhskt4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F37gjrja4scjv0pwhskt4.png" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
With the source cloned, compose.yaml was opened to inspect the service definitions. The mysql service specifies a persistent named volume (todo-mysql-data) so database data isn't lost when the container restarts, along with environment variables that set the root password and auto-create the todos database on first startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Build and Start the Multi-Container Stack&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn7py27h1ymywmyyd7vs6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn7py27h1ymywmyyd7vs6.png" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
Running docker compose up from the parent DOCKER COMPOSE folder failed with "no configuration file provided: not found", since Compose looks for compose.yaml in the current directory. Moving into the todo-list-app project folder and re-running the command resolved it: Compose pulled the node:22-alpine and mysql:8.0 images, created a dedicated network and volume, and started both containers successfully.&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 --build     # failed — wrong directory
cd todo-list-app
docker compose up -d --build     # succeeded — 19/19 steps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Troubleshooting note: docker compose commands must be run from the directory containing compose.yaml (or with the -f flag pointing to it).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Verify the Running Containers in Docker Desktop&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8h7jzk2jgmtwx3pjf3ov.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8h7jzk2jgmtwx3pjf3ov.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffq7a2z9btyrga1279965.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffq7a2z9btyrga1279965.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Switching to Docker Desktop's Containers view confirms the todo-list-app project group is live, with two healthy containers: app-1 running node:22-alpine and mapped to port 3000, and mysql-1 running mysql:8.0. Both show active CPU and memory usage, confirming the stack is up and communicating over its internal Docker network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Test the Live Application&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7719lmn7t8sde1cx50c1.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7719lmn7t8sde1cx50c1.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Finally, browsing to localhost:3000 confirms the full stack is working end-to-end: the Node.js frontend renders and reads/writes to-do items that are persisted in the MySQL container, with add, check-off, and delete actions all functioning against the live database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;p&gt;Starting from a cloned repository, this lab produced a fully functional, networked two-container application — a Node.js frontend and a MySQL database — orchestrated entirely through a single Docker Compose file and brought online with one command. Two realistic configuration errors were hit and resolved along the way, mirroring the kind of debugging that happens in real container deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills Demonstrated
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cloning and configuring application source repositories with Git&lt;/li&gt;
&lt;li&gt;Authoring and reading multi-service Docker Compose definitions&lt;/li&gt;
&lt;li&gt;Container orchestration: networks, named volumes, and service dependencies&lt;/li&gt;
&lt;li&gt;Environment-variable-driven database provisioning (MySQL)&lt;/li&gt;
&lt;li&gt;Debugging common Docker CLI and Git configuration errors&lt;/li&gt;
&lt;li&gt;Verifying containerized services through Docker Desktop and browser testing&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>From Local Node.js App to Automated AWS Deployment: A Full CI/CD Pipeline with GitHub Actions</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Fri, 07 Aug 2026 09:16:14 +0000</pubDate>
      <link>https://dev.to/awokay/from-local-nodejs-app-to-automated-aws-deployment-a-full-cicd-pipeline-with-github-actions-48n1</link>
      <guid>https://dev.to/awokay/from-local-nodejs-app-to-automated-aws-deployment-a-full-cicd-pipeline-with-github-actions-48n1</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This project documents a complete continuous deployment pipeline: a Node.js application built locally, pushed to GitHub, deployed onto a provisioned AWS EC2 instance, and finally automated so that every future git push triggers a hands-free deployment via GitHub Actions and SSH. It touches nearly every layer of a real DevOps workflow — app scaffolding, source control, cloud infrastructure, security groups, secrets management, and pipeline-as-code.&lt;/p&gt;

&lt;p&gt;Skills demonstrated: Node.js/Express project scaffolding, Git version control, GitHub repository management, AWS EC2 provisioning, security group configuration, SSH key-based server access, GitHub Actions workflow authoring (YAML), GitHub Secrets management, automated remote deployment scripting, process management with PM2.&lt;/p&gt;

&lt;p&gt;Screen-by-Screen Breakdown&lt;br&gt;
Screen 1 — Scaffolding the Node.js Project&lt;/p&gt;

&lt;p&gt;Initialized a new Node.js project from the command line, generating a package.json to track dependencies and scripts for the application.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F70nhee3tblceguct4hac.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F70nhee3tblceguct4hac.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Create and enter the project directory: mkdir aws-cicd-lab &amp;amp;&amp;amp; cd aws-cicd-lab.&lt;br&gt;
Run npm init -y to generate a default package.json.&lt;br&gt;
Confirm the file was created with the expected project metadata.&lt;br&gt;
Screen 2 — Installing Express and Defining the Start Script&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fscsezt0fvsv9fjd8csbz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fscsezt0fvsv9fjd8csbz.png" alt=" " width="800" height="405"&gt;&lt;/a&gt;&lt;br&gt;
Added a start script to package.json and installed Express as the project's web framework, preparing the app to serve HTTP responses.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Edit package.json to add "start": "node app.js" under scripts.&lt;br&gt;
Run npm install express.&lt;br&gt;
Confirm Express appears under dependencies in package.json.&lt;/p&gt;

&lt;p&gt;Screen 3 — Verifying the App Locally&lt;/p&gt;

&lt;p&gt;Ran the application locally and confirmed it served the expected response in the browser before pushing any code — catching issues early, before they reach the cloud.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyflq7x7f42saoez0wrpb.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyflq7x7f42saoez0wrpb.png" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Run npm start (or node app.js) locally.&lt;br&gt;
Open localhost:3000 in the browser.&lt;br&gt;
Confirm the expected response renders ("CI/CD Deployment Successful!").&lt;/p&gt;

&lt;p&gt;Screen 4 — Creating the GitHub Repository&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmca2tb65vonsnc00nt88.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmca2tb65vonsnc00nt88.png" alt=" " width="800" height="375"&gt;&lt;/a&gt;&lt;br&gt;
Created a new public GitHub repository (node-app-actions) to host the project's source code and serve as the trigger point for the deployment pipeline.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;On GitHub, click New repository.&lt;br&gt;
Set the Repository name (node-app-actions) and visibility (Public).&lt;br&gt;
Leave README/.gitignore/license unchecked (added manually).&lt;br&gt;
Click Create repository.&lt;/p&gt;

&lt;p&gt;Screen 5 — Reviewing the Push Instructions&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlgvx65anc3bri8i947v.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlgvx65anc3bri8i947v.png" alt=" " width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
Reviewed GitHub's auto-generated command-line instructions for connecting a local repository to the newly created remote.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Note the "push an existing repository from the command line" commands.&lt;br&gt;
Copy the git remote add origin URL for use in the local terminal.&lt;/p&gt;

&lt;p&gt;Screen 6 — Pushing the Local Repository to GitHub&lt;/p&gt;

&lt;p&gt;Connected the local Git repository to the GitHub remote and pushed the initial commit, making the codebase available as the deployment source.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuc871lims3unvy97xuko.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuc871lims3unvy97xuko.png" alt=" " width="800" height="403"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Run git remote add origin &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;https://github.com/&lt;/a&gt;/node-app-actions.git.&lt;br&gt;
Run git branch -M main.&lt;br&gt;
Run git push -u origin main.&lt;br&gt;
Confirm the push output shows objects written and the branch tracking origin/main.&lt;/p&gt;

&lt;p&gt;⚠️ Security note: This repo push included vpc-key.pem — the EC2 private key — as a tracked file in a public repository. A private key committed to a public repo is a live credential exposure, not just a portfolio detail. Before publishing this project: rotate/replace the EC2 key pair in AWS, remove the file from Git history (git filter-repo or BFG Repo-Cleaner — deleting it in a new commit isn't enough, history still has it), and add *.pem to .gitignore going forward. The project later handles the SSH key correctly via GitHub Secrets (Screens 15–16) — the same discipline should apply here too.&lt;/p&gt;

&lt;p&gt;Screen 7 — Launching the EC2 Instance&lt;/p&gt;

&lt;p&gt;Began provisioning a new AWS EC2 instance (nodeApp) using a free-tier-eligible Ubuntu 24.04 LTS image as the deployment target.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqlfqvgnb1y1wkhj3cuf1.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqlfqvgnb1y1wkhj3cuf1.png" alt=" " width="799" height="342"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;In the AWS Console, go to EC2 → Launch an instance.&lt;br&gt;
Set the Name (nodeApp).&lt;br&gt;
Under Quick Start, select Ubuntu → Ubuntu Server 24.04 LTS.&lt;br&gt;
Confirm the instance summary (AMI, instance type) before continuing.&lt;/p&gt;

&lt;p&gt;Screen 8 — Configuring Network Settings and Security Group&lt;/p&gt;

&lt;p&gt;Configured the instance's network settings, creating a new security group (node-app-nsg) with explicit inbound rules for SSH (port 22) and HTTP (port 80).&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F13a3xnlb2fdxbtmcbest.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F13a3xnlb2fdxbtmcbest.png" alt=" " width="800" height="492"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Under Network settings, confirm the VPC and subnet.&lt;br&gt;
Choose Create security group and name it (node-app-nsg).&lt;br&gt;
Add an inbound rule: Type SSH, Port 22, Source Anywhere (or restrict to your IP for better security).&lt;br&gt;
Add a second inbound rule: Type HTTP, Port 80.&lt;br&gt;
Click Launch instance.&lt;/p&gt;

&lt;p&gt;Screen 9 — Confirming the Instance Is Running&lt;/p&gt;

&lt;p&gt;Verified the new EC2 instance launched successfully, noting its public IP, instance type, and associated VPC/subnet details.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3vrxcz16zxdt0iq8bj08.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3vrxcz16zxdt0iq8bj08.png" alt=" " width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open EC2 → Instances and select the new instance.&lt;br&gt;
Confirm Instance state shows Running.&lt;br&gt;
Note the Public IPv4 address and Instance type (t3.micro) for later use.&lt;/p&gt;

&lt;p&gt;Screen 10 — Retrieving the SSH Connect Command&lt;/p&gt;

&lt;p&gt;Used the EC2 console's built-in Connect panel to generate the correct SSH command for accessing the instance, referencing the downloaded private key.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkkkzpmounvurwf6befzc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkkkzpmounvurwf6befzc.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Select the instance and click Connect.&lt;br&gt;
Open the SSH client tab.&lt;br&gt;
Note the chmod 400 command to secure the key file's permissions.&lt;br&gt;
Copy the generated SSH command (ssh -i ".pem" ubuntu@).&lt;/p&gt;

&lt;p&gt;Screen 11 — Connecting to the Instance via SSH&lt;/p&gt;

&lt;p&gt;Established an SSH session into the EC2 instance from the local terminal, confirming a clean Ubuntu boot with no pending critical issues.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fey0thp1rsoa4eo7u4dgc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fey0thp1rsoa4eo7u4dgc.png" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;In the local terminal, run the copied SSH command with the correct key path.&lt;br&gt;
Confirm the Ubuntu welcome banner and system status appear.&lt;br&gt;
Note the instance's internal IP for reference.&lt;/p&gt;

&lt;p&gt;Screen 12 — Preparing the Server (Nginx &amp;amp; SSH Keys)&lt;/p&gt;

&lt;p&gt;Enabled and started Nginx on the instance as a base web-facing service, then inspected the server's SSH key configuration to confirm what was authorized for access.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsm3grxzcz3i1i1vsu3ij.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsm3grxzcz3i1i1vsu3ij.png" alt=" " width="799" height="414"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Run sudo systemctl enable nginx.&lt;br&gt;
Run sudo systemctl start nginx.&lt;br&gt;
Inspect ~/.ssh/authorized_keys to confirm the expected public key is present.&lt;/p&gt;

&lt;p&gt;Screen 13 — Navigating to Repository Settings&lt;/p&gt;

&lt;p&gt;Opened the GitHub repository's Settings tab to begin configuring the secrets that GitHub Actions would need to deploy to the EC2 instance securely.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the repository on GitHub.&lt;br&gt;
Click the Settings tab.&lt;br&gt;
Locate Secrets and variables in the left sidebar.&lt;/p&gt;

&lt;p&gt;Screen 14 — Opening Actions Secrets&lt;/p&gt;

&lt;p&gt;Navigated into the Actions secrets section, where sensitive deployment values (host, username, private key) would be stored securely rather than hardcoded into the workflow file.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fou47ylklfdx44bqbosi6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fou47ylklfdx44bqbosi6.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Under Secrets and variables, click Actions.&lt;br&gt;
Confirm the Actions secrets panel is ready to accept new entries.&lt;/p&gt;

&lt;p&gt;Screen 15 — Adding the VM_HOST Secret&lt;/p&gt;

&lt;p&gt;Stored the EC2 instance's public IP as a GitHub Actions secret (VM_HOST), so the deployment workflow could reference it without exposing it in the codebase.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft120uktej9knvbz70l54.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft120uktej9knvbz70l54.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Click New repository secret.&lt;br&gt;
Set Name to VM_HOST.&lt;br&gt;
Set Secret to the EC2 public IP address.&lt;br&gt;
Click Add secret.&lt;/p&gt;

&lt;p&gt;Screen 16 — Preparing the SSH Private Key for a Secret&lt;/p&gt;

&lt;p&gt;Opened the EC2 private key file to copy its full contents, in preparation for storing it as a GitHub Actions secret (VM_SSH_KEY) rather than committing it to the repo.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7xsfrvx0frdyfoyncmg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7xsfrvx0frdyfoyncmg.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Open the .pem key file in a text editor.&lt;br&gt;
Select and copy the entire contents, including the BEGIN/END RSA PRIVATE KEY lines.&lt;br&gt;
Paste the full key into a new GitHub secret named VM_SSH_KEY.&lt;/p&gt;

&lt;p&gt;This is the correct way to handle the private key — as a GitHub Secret, never as a tracked file. It's worth applying the same standard retroactively to Screen 6.&lt;/p&gt;

&lt;p&gt;Screen 17 — Scaffolding the GitHub Actions Workflow&lt;/p&gt;

&lt;p&gt;Created the folder structure GitHub Actions requires (.github/workflows/) and an empty workflow file to hold the deployment pipeline definition.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F478z6r7yk3me7tbggwej.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F478z6r7yk3me7tbggwej.png" alt=" " width="799" height="367"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;From the project root, run mkdir .github.&lt;br&gt;
Run mkdir workflows inside it, then cd workflows.&lt;br&gt;
Run touch deploy.yml to create the workflow file.&lt;/p&gt;

&lt;p&gt;Screen 18 — Writing the Deployment Job&lt;/p&gt;

&lt;p&gt;Authored the core deployment step using the appleboy/ssh-action, referencing the GitHub Secrets to SSH into the EC2 instance and run a deploy script — cloning on first run, pulling and restarting via PM2 on subsequent runs.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftunh0242lfjh6o764n5u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftunh0242lfjh6o764n5u.png" alt=" " width="800" height="387"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Define a deploy job under jobs:.&lt;br&gt;
Add a step using uses: appleboy/&lt;a href="mailto:ssh-action@v0.1.10"&gt;ssh-action@v0.1.10&lt;/a&gt;.&lt;br&gt;
Reference secrets.VM_HOST, secrets.VM_USER, and secrets.VM_SSH_KEY under with:.&lt;br&gt;
Write the deploy script: — conditionally clone the repo, then git pull, npm install, and restart via pm2 restart app || pm2 start app.js --name app.&lt;br&gt;
Screen 19 — Adding the Checkout Step and Triggering the Pipeline&lt;/p&gt;

&lt;p&gt;Completed the workflow with a trigger (on: push) and a checkout step, then committed and pushed the workflow file — which immediately kicked off the first automated deployment.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuy4v5lyiifvdg7eh697z.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuy4v5lyiifvdg7eh697z.png" alt=" " width="799" height="412"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Add on: push: at the top of the workflow to trigger on every push to the branch.&lt;br&gt;
Add a Checkout Code step using actions/&lt;a href="mailto:checkout@v3"&gt;checkout@v3&lt;/a&gt;.&lt;br&gt;
Run git add .github/, git commit -m "added aws workflow file", and git push origin main.&lt;br&gt;
Watch the Actions tab on GitHub to confirm the workflow runs and deploys successfully.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>gitlab</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Azure Network Foundations: Provisioning a Secure VNet, NSG-Governed Subnets &amp; SSH-Accessible Linux VM</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Fri, 07 Aug 2026 07:39:51 +0000</pubDate>
      <link>https://dev.to/awokay/azure-network-foundations-provisioning-a-secure-vnet-nsg-governed-subnets-ssh-accessible-linux-2ojd</link>
      <guid>https://dev.to/awokay/azure-network-foundations-provisioning-a-secure-vnet-nsg-governed-subnets-ssh-accessible-linux-2ojd</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This project documents the foundational networking layer that most Azure workloads sit on top of: a Virtual Network (VNet), address-space planning via subnets, and traffic control through Network Security Groups (NSGs). It closes the loop by provisioning a Linux virtual machine into that network and connecting to it over SSH — proving the network, security rules, and compute layer all work together end to end.&lt;/p&gt;

&lt;p&gt;Skills demonstrated: VNet and subnet design (CIDR planning), Network Security Group configuration, inbound/outbound rule prioritization, custom SSH access rules, VM provisioning with SSH key-pair authentication, NIC-to-subnet association, public IP assignment, secure remote access verification.&lt;/p&gt;

&lt;p&gt;Screen-by-Screen Breakdown&lt;br&gt;
Screen 1 — Creating the Virtual Network&lt;/p&gt;

&lt;p&gt;Provisioned a new Virtual Network (KOLAVN_RG) inside a dedicated resource group, establishing the foundational address space that all subnets and resources in this project would live inside.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcdl303oan41c6f3a3m6t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcdl303oan41c6f3a3m6t.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Navigate to Virtual networks → Create virtual network.&lt;br&gt;
Under Project details, create a new resource group (KOLAVN_RG).&lt;br&gt;
Under Instance details, name the virtual network and select the region (West US).&lt;br&gt;
Move to the IP addresses tab to configure the address space.&lt;/p&gt;

&lt;p&gt;Screen 2 — Configuring the First Subnet&lt;/p&gt;

&lt;p&gt;Defined the first subnet (kola_subnet) within the VNet's address space, setting a /24 range to segment part of the network for later resource placement.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgkd52ua45gvy73zk2b4t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgkd52ua45gvy73zk2b4t.png" alt=" " width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;On the IP addresses tab, click Add a subnet.&lt;br&gt;
Name the subnet (kola_subnet).&lt;br&gt;
Confirm the IPv4 address range (10.0.0.0/16) and set the starting address (10.0.1.0).&lt;br&gt;
Set the subnet size (/24, 256 addresses).&lt;br&gt;
Click Add, then proceed to Review + create.&lt;/p&gt;

&lt;p&gt;Screen 3 — Confirming the VNet Deployment&lt;/p&gt;

&lt;p&gt;Verified the Virtual Network deployment completed successfully before moving on to add further subnets and security configuration.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3jurzx324vmef2p70j2p.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3jurzx324vmef2p70j2p.png" alt=" " width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Wait for the deployment to finish.&lt;br&gt;
Confirm the green "Your deployment is complete" status.&lt;br&gt;
Click Go to resource to open the new VNet.&lt;/p&gt;

&lt;p&gt;Screen 4 — Reviewing Subnets Before Adding Security&lt;/p&gt;

&lt;p&gt;Checked the VNet's subnet list after adding a second subnet (kola_sub2), noting that neither subnet yet had a Network Security Group attached — flagging the next task.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs5q4u8zq8sow0hj0gmjf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs5q4u8zq8sow0hj0gmjf.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the VNet and go to Settings → Subnets.&lt;br&gt;
Review the subnet list: names, IPv4 ranges, and available IPs.&lt;br&gt;
Note the Security group column is empty for both subnets — this is the gap to close next.&lt;/p&gt;

&lt;p&gt;Screen 5 — Navigating to Network Security Groups&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp4n9o553jmq6ezzx1qrx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp4n9o553jmq6ezzx1qrx.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;br&gt;
Used the global Azure search to jump directly to the Network Security Groups service, in preparation for creating and attaching a security boundary to the subnets.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Click the top search bar in the Azure Portal.&lt;br&gt;
Search "network security group."&lt;br&gt;
Select Network security groups from the Recent services list.&lt;/p&gt;

&lt;p&gt;Screen 6 — Reviewing the Network Security Group's Default Rules&lt;/p&gt;

&lt;p&gt;Opened the newly associated NSG (kolaweb) and reviewed its default inbound and outbound rules — the baseline Azure applies automatically (allow VNet traffic, allow Azure Load Balancer, deny everything else by 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuqjp7bnzncb84kakgqqx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuqjp7bnzncb84kakgqqx.png" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Open the NSG resource (kolaweb).&lt;br&gt;
Review Essentials: resource group, location, subscription.&lt;br&gt;
Review the default Inbound Security Rules (AllowVnetInBound, AllowAzureLoadBalancerInBound, DenyAllInBound) and Outbound Security Rules.&lt;br&gt;
Navigate to Settings → Inbound security rules to add a custom rule.&lt;/p&gt;

&lt;p&gt;Screen 7 — Opening Inbound Security Rules&lt;/p&gt;

&lt;p&gt;Confirmed the current inbound rule set before adding a custom rule to explicitly allow SSH traffic to the VM that would later sit behind this &lt;br&gt;
NSG.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0mg287oo9nj4do1vy4g.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0mg287oo9nj4do1vy4g.png" alt=" " width="799" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Go to Settings → Inbound security rules.&lt;br&gt;
Review existing default rules and priorities.&lt;br&gt;
Click + Add to create a new custom rule.&lt;/p&gt;

&lt;p&gt;Screen 8 — Adding a Custom SSH Inbound Rule&lt;/p&gt;

&lt;p&gt;Created a dedicated inbound rule permitting SSH traffic (TCP port 22), explicitly named and documented so the rule's purpose would be clear to anyone auditing the NSG later.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F80vsjiytdf2d40htx59j.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F80vsjiytdf2d40htx59j.png" alt=" " width="800" height="434"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;In Service, select SSH (auto-fills TCP port 22).&lt;br&gt;
Set Protocol to TCP and Action to Allow.&lt;br&gt;
Set Priority (e.g. 100) — lower numbers are evaluated first.&lt;br&gt;
Name the rule (SSH_NETWORK) and add a description ("Connect SSH network").&lt;br&gt;
Click Add to save the rule.&lt;/p&gt;

&lt;p&gt;Screen 9 — Starting Virtual Machine Creation&lt;/p&gt;

&lt;p&gt;With the network and security layer in place, began provisioning a virtual machine to deploy into the secured 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx77dmgtv37e39atzuq1z.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx77dmgtv37e39atzuq1z.png" alt=" " width="800" height="442"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Navigate to Virtual machines under Compute infrastructure.&lt;br&gt;
Confirm no existing VMs are listed.&lt;br&gt;
Click + Create to start the VM creation wizard.&lt;/p&gt;

&lt;p&gt;Screen 10 — Configuring VM Basics&lt;/p&gt;

&lt;p&gt;Configured the core VM settings: name, region, a cost-efficient Ubuntu image and size, and SSH public-key authentication instead of a password for secure, auditable access.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdhfcbhiupsrt4djjpq4z.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdhfcbhiupsrt4djjpq4z.png" alt=" " width="799" height="460"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Set Virtual machine name (KOLA-VM) and Region (West US).&lt;br&gt;
Choose the Image (Ubuntu Server 24.04 LTS) and Size (Standard_D2s_v3).&lt;br&gt;
Set Authentication type to SSH public key.&lt;br&gt;
Set the Username (azureuser) and Key pair name (KOLA-VM_key).&lt;br&gt;
Set Public inbound ports to None (access will be governed by the NSG rule instead).&lt;/p&gt;

&lt;p&gt;Screen 11 — Attaching the VM to the Secured Subnet&lt;/p&gt;

&lt;p&gt;Connected the VM's network interface to the previously created VNet and subnet, assigned a new public IP, and applied the NSG containing the SSH rule — tying the whole project together at the networking layer.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhq4lr18u7t4luoun6i6y.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhq4lr18u7t4luoun6i6y.png" alt=" " width="799" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Go to the Networking tab.&lt;br&gt;
Confirm Virtual network (KOLAVN_RG) and select Subnet (kola_subnet, 10.0.1.0/24).&lt;br&gt;
Confirm a new Public IP will be created.&lt;br&gt;
Set NIC network security group to Basic (or Advanced to select the custom NSG directly).&lt;br&gt;
Leave accelerated networking enabled for better throughput, then click Review + create.&lt;/p&gt;

&lt;p&gt;Screen 12 — Validating and Generating the SSH Key Pair&lt;/p&gt;

&lt;p&gt;Passed validation on the VM configuration and generated a new SSH key pair, downloading the private key — the only copy, since Azure does not retain it after generation.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq4alhe0avr2upladzrwl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq4alhe0avr2upladzrwl.png" alt=" " width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Confirm "Validation passed" at the top of the Review + create tab.&lt;br&gt;
Review the configuration summary (resource group, VM name, region, security type).&lt;br&gt;
In the Generate new key pair dialog, click Download private key and create resource.&lt;br&gt;
Store the downloaded .pem file securely — it cannot be re-downloaded later.&lt;/p&gt;

&lt;p&gt;Screen 13 — Connecting to the VM via Native SSH&lt;/p&gt;

&lt;p&gt;Used the Azure Portal's built-in Connect blade to generate and run the correct SSH command, pointing to the downloaded private key, to establish a secure remote session into the new VM.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgpvht5tuzuv1uf48pd8s.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgpvht5tuzuv1uf48pd8s.png" alt=" " width="799" height="424"&gt;&lt;/a&gt;&lt;br&gt;
Steps:&lt;/p&gt;

&lt;p&gt;Open the VM and go to Connect → Connect.&lt;br&gt;
Select Native SSH, and confirm the destination VM's public IP and port (22).&lt;br&gt;
Provide the local path to the downloaded private key file.&lt;br&gt;
Copy the generated SSH command (ssh -i "" azureuser@).&lt;br&gt;
Run it in a local terminal to connect.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>networking</category>
      <category>webdev</category>
      <category>nsg</category>
    </item>
    <item>
      <title>Deploying and Exposing a Scalable NGINX Web Service on Azure Kubernetes Service (AKS)</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Fri, 07 Aug 2026 05:44:05 +0000</pubDate>
      <link>https://dev.to/awokay/deploying-and-exposing-a-scalable-nginx-web-serviceon-azure-kubernetes-service-aks-10bb</link>
      <guid>https://dev.to/awokay/deploying-and-exposing-a-scalable-nginx-web-serviceon-azure-kubernetes-service-aks-10bb</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This lab demonstrates a complete, production-style workflow for standing up a containerized web application on Microsoft Azure using Azure Kubernetes Service (AKS). It covers cluster provisioning via the Azure CLI, secure node authentication, namespace-based workload isolation, application deployment, and public exposure through a cloud-native Load Balancer — the same pattern used to ship containerized services in real DevOps environments.&lt;br&gt;
The objective was to take a project from a completely empty Azure subscription to a live, internet-reachable NGINX service, while documenting every command and its output for reproducibility and portfolio presentation.&lt;/p&gt;

&lt;p&gt;Tools &amp;amp; Technologies&lt;/p&gt;

&lt;p&gt;Microsoft Azure — Resource Groups, Azure Kubernetes Service (AKS), Load Balancer, Virtual Machine Scale Sets&lt;br&gt;
Azure CLI (az) — cluster and resource provisioning&lt;br&gt;
Kubernetes / kubectl — namespace, deployment, and service management&lt;br&gt;
NGINX — containerized workload deployed to the cluster&lt;br&gt;
VS Code + PowerShell — local development and terminal environment&lt;br&gt;
SSH (ED25519) — secure node authentication&lt;/p&gt;

&lt;p&gt;Architecture at a Glance&lt;br&gt;
A resource group (kolakub-RG) hosts the AKS control plane, while Azure auto-generates a companion managed resource group (myNodeRG) containing the underlying VM Scale Set, virtual network, network security group, and Load Balancer that back the cluster's worker nodes. Inside the cluster, a dedicated frontend namespace isolates the NGINX deployment, which is exposed externally through a Kubernetes Service of type LoadBalancer.&lt;/p&gt;

&lt;p&gt;Step-by-Step Walkthrough&lt;/p&gt;

&lt;p&gt;STEP 1  Generate an SSH Key Pair for Node Authentication&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftb5misvlnpth066b3wn2.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftb5misvlnpth066b3wn2.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;br&gt;
he command produced a private key (aks-ssh) and a public key (aks-ssh.pub), which is later injected into the AKS cluster so nodes can be reached over SSH without password authentication.&lt;/p&gt;

&lt;p&gt;Every AKS Linux node needs an SSH key for secure administrative access. Working inside the LAB-1 project folder in VS Code's PowerShell terminal, a dedicated .ssh directory was created, followed by an ED25519 key pair generated specifically for this cluster.&lt;/p&gt;

&lt;p&gt;STEP 2  Create a Resource Group&lt;/p&gt;

&lt;p&gt;Before any Azure resource can be provisioned, it needs a resource group to live in. The subscription was first checked for existing groups, then a new one — kolakub-RG — was created in the West US region.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3p6psm28i8zoiv6dh678.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3p6psm28i8zoiv6dh678.png" alt=" " width="800" height="368"&gt;&lt;/a&gt;&lt;br&gt;
The returned JSON confirms the resource group was created successfully and is ready to host the AKS cluster&lt;/p&gt;

&lt;p&gt;STEP 3  Provision the AKS Cluster&lt;/p&gt;

&lt;p&gt;With the resource group in place, the AKS cluster itself — MyAKSCluster — was provisioned using az aks create. The configuration defines a single-node systemp nodepool on Standard_D2s_v3 VMs, injects the previously generated SSH public key, uses the Azure CNI network plugin, and enables the cluster autoscaler (scaling between 1 and 2 nodes) so the workload can grow automatically under load.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1mu2zcukbxcm9gss8nrf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1mu2zcukbxcm9gss8nrf.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Azure CLI streams back the complete cluster definition, confirming settings such as autoscaling, node pool profile, and orchestrator version once provisioning completes.&lt;/p&gt;

&lt;p&gt;STEP 4  Verify the Cluster in the Azure Portal&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyfltjwg82zh9xs13xwmq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyfltjwg82zh9xs13xwmq.png" alt=" " width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
Switching to the Azure Portal confirms the cluster was created successfully outside the CLI as well. Inside kolakub-RG, MyAKSCluster appears with resource type "Kubernetes service", deployed to the West US region.&lt;/p&gt;

&lt;p&gt;STEP 5  Inspect the Auto-Generated Node Resource Group&lt;br&gt;
AKS automatically creates a second, system-managed resource group (myNodeRG) to hold the infrastructure backing the cluster's nodes. Reviewing it surfaces the public IP address, the network security group, the virtual machine scale set running the actual worker node(s), the virtual network, the Load Balancer, and the managed identity used by the cluster.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj84qwcmdgv1abyqawsbw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj84qwcmdgv1abyqawsbw.png" alt=" " width="800" height="463"&gt;&lt;/a&gt;&lt;br&gt;
This separation keeps user-managed resources (kolakub-RG) cleanly apart from Azure-managed cluster infrastructure (myNodeRG).&lt;/p&gt;

&lt;p&gt;STEP 6  Create an Isolated Namespace&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frskm392vxapfkieyejs0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frskm392vxapfkieyejs0.png" alt=" " width="800" height="193"&gt;&lt;/a&gt;&lt;br&gt;
To keep the application workload logically separated from system components, a dedicated frontend namespace was created using kubectl, then verified against the cluster's full namespace list.&lt;/p&gt;

&lt;p&gt;STEP 7  Deploy the NGINX Application&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe2q367e519ajk28b87in.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe2q367e519ajk28b87in.png" alt=" " width="799" height="206"&gt;&lt;/a&gt;&lt;br&gt;
With the namespace ready, an NGINX deployment was rolled out into frontend. Checking the default namespace first confirms no resources exist there — the workload is correctly scoped — while querying across all namespaces and then filtering to frontend shows the deployment running with all 3 replicas ready and available.&lt;/p&gt;

&lt;p&gt;STEP 8  Expose the Deployment with a LoadBalancer Service&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgby99bszjmj878e6sts5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgby99bszjmj878e6sts5.png" alt=" " width="800" height="63"&gt;&lt;/a&gt;&lt;br&gt;
To make the NGINX deployment reachable from outside the cluster, it was exposed as a Kubernetes Service of type LoadBalancer, mapping external port 80 over TCP to the pods.&lt;/p&gt;

&lt;p&gt;STEP 9  Connect kubectl to the Cluster &amp;amp; Confirm Node Health&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1wp2ytz8ktmxnegxsi8n.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1wp2ytz8ktmxnegxsi8n.png" alt=" " width="798" height="133"&gt;&lt;/a&gt;&lt;br&gt;
To manage the cluster from the local machine, its credentials were merged into the local kubeconfig with az aks get-credentials. A quick kubectl get node confirms the worker node is Ready and running Kubernetes v1.34.6.&lt;/p&gt;

&lt;p&gt;STEP 10  Validate Public Access via the External IP&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01l9e1ki444j6nodj3ok.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01l9e1ki444j6nodj3ok.png" alt=" " width="800" height="64"&gt;&lt;/a&gt;&lt;br&gt;
The final check confirms the service is live on the public internet. Querying the frontend namespace's services shows nginx-service of type LoadBalancer with an assigned EXTERNAL-IP, reachable on port 80 — proof the NGINX application is now publicly accessible.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aks</category>
      <category>nginx</category>
      <category>web</category>
    </item>
    <item>
      <title>From Commit to Cloud: CI/CD Deployment of a PHP eLearning Platform to Azure App Service via GitHub Actions</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Thu, 06 Aug 2026 16:49:22 +0000</pubDate>
      <link>https://dev.to/awokay/from-commit-to-cloud-cicd-deployment-of-a-php-elearning-platform-to-azure-app-service-via-github-8cj</link>
      <guid>https://dev.to/awokay/from-commit-to-cloud-cicd-deployment-of-a-php-elearning-platform-to-azure-app-service-via-github-8cj</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This project documents a complete CI/CD deployment loop for a PHP-based eLearning platform. It starts at the very beginning—initializing version control on a local project—and follows the code through GitHub into an Azure Web App wired for continuous deployment, ending with a live, publicly accessible site verified in the browser. It's a practical demonstration of how source control, cloud hosting, and automated build pipelines connect into a single working system.&lt;/p&gt;

&lt;p&gt;Skills demonstrated: Git version control fundamentals (init, add, and status); GitHub repository management; Azure App Service provisioning; GitHub-to-Azure Deployment Center integration; GitHub Actions build pipelines; PHP runtime configuration on Linux App Service; deployment log verification; and live production validation.&lt;/p&gt;

&lt;p&gt;Screen-by-Screen Breakdown&lt;br&gt;
Screen 1 — Initializing Git and Staging the Project&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxt6xjd5dj2kp6wtxloza.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxt6xjd5dj2kp6wtxloza.png" alt=" " width="800" height="411"&gt;&lt;/a&gt;&lt;br&gt;
Initialized a local Git repository inside the eLearning project folder in VS Code and staged all project files — HTML/PHP pages, styles, scripts, and assets — for the first commit.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the project folder (elearning) in VS Code.&lt;br&gt;
Open the integrated terminal and run &lt;code&gt;git init&lt;/code&gt; to create a local repository.&lt;br&gt;
Run &lt;code&gt;git add .&lt;/code&gt; to stage all files.&lt;br&gt;
Note the LF-to-CRLF line-ending warnings (expected on Windows; Git will normalize line endings automatically — not an error).&lt;/p&gt;

&lt;p&gt;Screen 2 — Reviewing Git Status Before the First Commit&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F38fvww1rj1malscakgfp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F38fvww1rj1malscakgfp.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verified exactly which files were staged before committing, confirming the full project structure — PHP pages, CSS, images, and library assets — was ready to be tracked.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Run git status to review staged changes.&lt;br&gt;
Confirm the branch is master with no commits yet.&lt;br&gt;
Review the full list of new files under "Changes to be committed."&lt;br&gt;
Proceed to git commit and set up the remote origin (not pictured, but the natural next step).&lt;/p&gt;

&lt;p&gt;Screen 3 — Pushing the Repository to GitHub&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr13dofkoahgksz7nhou6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr13dofkoahgksz7nhou6.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;br&gt;
Pushed the committed project to a public GitHub repository (kolarinde/kola-elearning), making the source code available as the deployment source for Azure.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Create a new repository on GitHub (kola-elearning).&lt;br&gt;
Add it as a remote: git remote add origin .&lt;br&gt;
Push the code: git push -u origin master.&lt;br&gt;
Confirm the files appear on GitHub under the master branch with the commit message "Adding code files."&lt;/p&gt;

&lt;p&gt;Screen 4 — Provisioning the Azure App Service&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8f88lmwpypwgaq7flu3v.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8f88lmwpypwgaq7flu3v.png" alt=" " width="799" height="359"&gt;&lt;/a&gt;&lt;br&gt;
Created and reviewed the Azure Web App (kolaAPP2), confirming it was running on a Linux-based App Service Plan in West US 3, with the GitHub repository already linked as its project source.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;In the Azure Portal, navigate to App Services and open the Web App (kolaAPP2).&lt;br&gt;
Review the Overview blade: resource group, default domain, status, App Service plan, region, and OS.&lt;br&gt;
Confirm the GitHub project link matches the intended repository.&lt;/p&gt;

&lt;p&gt;Screen 5 — Connecting Azure to GitHub via Deployment Center&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9s3wl6rj4wui6ixdfdf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu9s3wl6rj4wui6ixdfdf.png" alt=" " width="799" height="340"&gt;&lt;/a&gt;&lt;br&gt;
Configured the Deployment Center to source code directly from GitHub, selecting the correct organization, repository, and branch, with GitHub Actions as the build provider and PHP as the runtime stack.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open Deployment → Deployment Center on the Web App.&lt;br&gt;
Set the source to GitHub and authorize the connection.&lt;br&gt;
Select the GitHub organization (kolarinde), repository (kola-elearning), and branch (master).&lt;br&gt;
Confirm the build provider is set to GitHub Actions and the runtime stack to PHP.&lt;br&gt;
Save — Azure automatically generates a GitHub Actions workflow file in the repository.&lt;/p&gt;

&lt;p&gt;Screen 6 — Verifying the GitHub Actions Deployment Log&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8qvkk8dh23fr6l7k2va.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8qvkk8dh23fr6l7k2va.png" alt=" " width="800" height="391"&gt;&lt;/a&gt;&lt;br&gt;
Confirmed the automated deployment triggered by the GitHub Actions workflow completed successfully, reviewing the deployment log entry for status and timing.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;In Deployment Center, open the Logs tab.&lt;br&gt;
Locate the latest deployment entry by date.&lt;br&gt;
Confirm Status shows "Succeeded," and the log source is linked to the app logs.&lt;br&gt;
Click into the log entry for full build/deploy details if troubleshooting is needed.&lt;/p&gt;

&lt;p&gt;Screen 7 — Validating the Live Deployed Application&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flnhvdu57lt1pmcb3em4a.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flnhvdu57lt1pmcb3em4a.png" alt=" " width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
Opened the live Azure-hosted domain in the browser to confirm the eLearning platform deployed correctly, rendering the full site—navigation, course cards, and imagery—from the automated pipeline.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Copy the App Service default domain from the Overview blade (*.azurewebsites.net).&lt;br&gt;
Open it in a new browser tab.&lt;br&gt;
Verify the site renders correctly: navigation, hero content, and course listings.&lt;br&gt;
Spot-check a few pages/links to confirm assets (CSS, images) loaded correctly from the deployed build.&lt;/p&gt;

</description>
      <category>github</category>
      <category>cicd</category>
      <category>php</category>
      <category>azure</category>
    </item>
    <item>
      <title>Infrastructure as Code: Modular Multi-Resource Azure Deployment with ARM Templates &amp; CLI</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Thu, 06 Aug 2026 06:41:03 +0000</pubDate>
      <link>https://dev.to/awokay/infrastructure-as-code-modular-multi-resource-azure-deployment-with-arm-templates-cli-ph3</link>
      <guid>https://dev.to/awokay/infrastructure-as-code-modular-multi-resource-azure-deployment-with-arm-templates-cli-ph3</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This project documents a modular Azure deployment pipeline built entirely through the Azure CLI and ARM (Azure Resource Manager) templates in VS Code. Each Azure resource — Key Vault, Storage Account, and Web App — was isolated into its own project folder with dedicated template.json and parameters.json files, deployed into its own resource group. The walkthrough also captures genuine debugging moments: resolving a missing-file path error and repeated DNS/connectivity failures against management.azure.com, both handled through methodical retries rather than guesswork.&lt;/p&gt;

&lt;p&gt;Skills demonstrated: ARM template authoring &amp;amp; parameterization, Azure CLI deployment workflows (az group create, az deployment group create), resource group isolation per workload, working-directory/path troubleshooting, transient network error diagnosis and recovery, modular Infrastructure-as-Code project structure.&lt;/p&gt;

&lt;p&gt;Screen-by-Screen Breakdown&lt;br&gt;
Screen 1 — Verifying Azure Session &amp;amp; Provisioning the Key Vault Resource Group&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd7bzhwj36hrchmw2t91w.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd7bzhwj36hrchmw2t91w.png" alt=" " width="800" height="569"&gt;&lt;/a&gt;&lt;br&gt;
Confirmed the active Azure CLI session and subscription context before provisioning, then worked through a transient DNS resolution failure on a listing command to successfully create a dedicated resource group for the Key Vault module.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the integrated PowerShell terminal in VS Code.&lt;br&gt;
Run az account list to confirm the active subscription, tenant, and signed-in user.&lt;br&gt;
Run az group list to check existing resource groups (encountered a transient getaddrinfo failed DNS error against management.azure.com).&lt;br&gt;
Run az group create -n key-rg -l westus3 to provision a new resource group scoped to the Key Vault deployment.&lt;br&gt;
Confirm success via the returned JSON ("provisioningState": "Succeeded").&lt;/p&gt;

&lt;p&gt;Screen 2 — Deploying the Key Vault ARM Template&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqowjq8aovisq5j4goidy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqowjq8aovisq5j4goidy.png" alt=" " width="800" height="576"&gt;&lt;/a&gt;&lt;br&gt;
Deployed a parameterized ARM template into key-rg, first resolving a working-directory mismatch, then supplying required parameters interactively and retrying past a transient connectivity error until the Key Vault deployment completed.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Attempt az deployment group create --resource-group key-rg --template-file template.json from the ARM-Templates root — fails (No such file or directory: 'template.json').&lt;br&gt;
Run cd keyvault to move into the correct template directory.&lt;br&gt;
Re-run the deployment command; the CLI interactively prompts for required parameters (vaultName, keyName).&lt;br&gt;
Supply parameter values (e.g. nazarethvault, nazarethkey).&lt;br&gt;
Retry after a transient DNS/connection error.&lt;br&gt;
Confirm the successful deployment output, showing the dependency on Microsoft.KeyVault/vaults/nazarethvault.&lt;/p&gt;

&lt;p&gt;Screen 3 — Provisioning and Deploying the Storage Module&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxnwqric5494nyiat6mz4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxnwqric5494nyiat6mz4.png" alt=" " width="800" height="542"&gt;&lt;/a&gt;&lt;br&gt;
Created a second, isolated resource group for the storage workload, pushed through repeated transient Azure Resource Manager connectivity errors, and deployed the storage ARM template from its own dedicated directory.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Run az group create -n storageRG -l "westus3" — retried after two consecutive DNS resolution failures.&lt;br&gt;
Confirm resource group creation ("provisioningState": "Succeeded").&lt;br&gt;
Navigate out of the previous module and into the storage template folder: cd .. then cd storage-lab.&lt;br&gt;
Run az deployment group create --resource-group storageRG --template-file storage.json.&lt;br&gt;
Retry through further transient connection errors until the deployment succeeds.&lt;br&gt;
Confirm the deployment output (deployment name: storage).&lt;/p&gt;

&lt;p&gt;Screen 4 — Modular Project Structure &amp;amp; Web App Parameters&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fch2jtogidplacuuga2j4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fch2jtogidplacuuga2j4.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;br&gt;
Organized the full IaC project into clean, per-resource folders and configured the Web App module's parameters file ahead of deployment, keeping each resource's template and parameter definitions self-contained.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Structure the root ARM-Templates project into isolated subfolders: keyvault, storage-lab, webapp.&lt;br&gt;
Open webapp/parameters.json.&lt;br&gt;
Define parameter values, including webAppName (e.g. ChlarityApp43564) and appServicePlanName.&lt;br&gt;
Review the terminal history confirming the prior successful Key Vault and Storage deployments.&lt;br&gt;
Proceed to deploy the Web App module using the same az deployment group create --resource-group  --template-file template.json` pattern.&lt;/p&gt;

</description>
      <category>infrastructureascode</category>
      <category>cli</category>
      <category>azure</category>
    </item>
    <item>
      <title>Provisioning and Securing Azure Blob Storage: End-to-End Deployment Walkthrough</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Wed, 05 Aug 2026 21:08:53 +0000</pubDate>
      <link>https://dev.to/awokay/provisioning-and-securing-azure-blob-storage-end-to-end-deployment-walkthrough-i9m</link>
      <guid>https://dev.to/awokay/provisioning-and-securing-azure-blob-storage-end-to-end-deployment-walkthrough-i9m</guid>
      <description>&lt;p&gt;Project Overview&lt;/p&gt;

&lt;p&gt;This project documents the full lifecycle of setting up an Azure Blob Storage solution — from creating the storage account through to uploading and publishing a file for public access. It covers core Azure concepts: resource groups, storage redundancy tiers, container-level access control, and blob-level configuration, all performed directly through the Azure Portal.&lt;/p&gt;

&lt;p&gt;Skills demonstrated: Azure Storage Account provisioning, resource group management, data redundancy strategy (LRS), storage configuration (TLS, access tiers, anonymous access policy), container and blob lifecycle management, access-level security controls.&lt;/p&gt;

&lt;p&gt;Screen 1 — Creating the Storage 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsi9lxbfvrxfh8iiivoma.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsi9lxbfvrxfh8iiivoma.png" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;br&gt;
Configured a new storage account (kolastorage1) under a dedicated resource group (kola_storage) in the West US 3 region. Selected Blob Storage as the preferred storage type with Standard performance and Locally-Redundant Storage (LRS) for cost-efficient redundancy.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Navigate to Create a storage account in the Azure Portal.&lt;br&gt;
Select the subscription and create/select a resource group (kola_storage).&lt;br&gt;
Enter a unique storage account name (kolastorage1).&lt;br&gt;
Choose the region (West US 3).&lt;br&gt;
Set Preferred storage type to Azure Blob Storage / Data Lake Storage Gen2.&lt;br&gt;
Choose Standard performance and Locally-redundant storage (LRS) for redundancy.&lt;br&gt;
Click Review + create.&lt;/p&gt;

&lt;p&gt;Screen 2 — Reviewing and Deploying&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcg85jg7ohhng66dt4nho.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcg85jg7ohhng66dt4nho.png" alt=" " width="800" height="391"&gt;&lt;/a&gt;&lt;br&gt;
Reviewed all configuration settings against the defaults before confirming deployment, ensuring the resource group, region, and redundancy settings matched the project plan prior to provisioning.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;On the Review + create tab, verify Subscription, Resource group, Location, and Storage account name.&lt;br&gt;
Confirm Performance and Replication settings.&lt;br&gt;
Click Create to trigger deployment.&lt;br&gt;
Wait for the "Initializing deployment" confirmation.&lt;/p&gt;

&lt;p&gt;Screen 3 — Configuring Storage Account 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjc3hs7cqlnohar7xwysr.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjc3hs7cqlnohar7xwysr.png" alt=" " width="799" height="343"&gt;&lt;/a&gt;&lt;br&gt;
Adjusted account-level configuration, enabling Blob anonymous access and storage account key access to support later public blob access, and set the default access tier to Cool for infrequently accessed data.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the storage account and go to Settings → Configuration.&lt;br&gt;
Enable Allow Blob anonymous access.&lt;br&gt;
Enable Allow storage account key access.&lt;br&gt;
Set Minimum TLS version to 1.2 for secure transport.&lt;br&gt;
Set Blob access tier (default) to Cool.&lt;br&gt;
Click Save.&lt;/p&gt;

&lt;p&gt;Screen 4 — Setting Redundancy&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1z3gxp8faqx86ryxzqf0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1z3gxp8faqx86ryxzqf0.png" alt=" " width="799" height="359"&gt;&lt;/a&gt;&lt;br&gt;
Confirmed the storage redundancy configuration under the Redundancy blade, verifying Locally-Redundant Storage (LRS) was applied and the primary data center (West US 3) was active and available.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Go to Data management → Redundancy.&lt;br&gt;
Confirm or update the redundancy option (LRS).&lt;br&gt;
Review the storage endpoint location and status.&lt;br&gt;
Click Save.&lt;/p&gt;

&lt;p&gt;Screen 5 — Creating a Blob Container&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F17u1nohf9gj0devh8fj5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F17u1nohf9gj0devh8fj5.png" alt=" " width="800" height="366"&gt;&lt;/a&gt;&lt;br&gt;
Created a new container (kolastorage) within the storage account to logically organize blob data, setting the initial anonymous access level to private.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Go to Data storage → Containers.&lt;br&gt;
Click + Add container.&lt;br&gt;
Enter a container name (kolastorage).&lt;br&gt;
Click Create.&lt;/p&gt;

&lt;p&gt;Screen 6 — Verifying Container Creation&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ytdaceu1reenxqkueml.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ytdaceu1reenxqkueml.png" alt=" " width="799" height="350"&gt;&lt;/a&gt;&lt;br&gt;
Confirmed the new container appeared alongside the default $logs container, with private access level and available lease state, validating successful creation.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Go to Containers under Data storage.&lt;br&gt;
Confirm the new container is listed.&lt;br&gt;
Select it to proceed to container-level settings.&lt;/p&gt;

&lt;p&gt;Screen 7 — Opening Container Access Controls&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpgtx7ot2nchu8nbuup0x.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpgtx7ot2nchu8nbuup0x.png" alt=" " width="799" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Opened the container's management pane to review upload options and access-level controls before publishing content.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Open the container (kolastorage).&lt;br&gt;
Review the toolbar options: Add Directory, Upload, Change access level.&lt;br&gt;
Click Change access level to proceed.&lt;/p&gt;

&lt;p&gt;Screen 8 — Setting Public Blob Access&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1cq2tsl7ako72176i83.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1cq2tsl7ako72176i83.png" alt=" " width="799" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Changed the container's anonymous access level to allow public read access to individual blobs, while keeping the container listing itself private — a common pattern for publishing static assets without exposing the full container index.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;In Change access level, set Anonymous access level to "Blob (anonymous read access for blobs only)".&lt;br&gt;
Click OK to apply.&lt;/p&gt;

&lt;p&gt;Screen 9 — Uploading a Blob&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdvqbst5ypeiel0yqcql.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdvqbst5ypeiel0yqcql.png" alt=" " width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uploaded a file into the container using the drag-and-drop upload panel, making it available for storage and later retrieval via a public URL.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Click Upload in the container toolbar.&lt;br&gt;
Drag and drop the file, or browse to select it.&lt;br&gt;
Click Upload to complete the transfer.&lt;/p&gt;

&lt;p&gt;Screen 10 — Verifying the Uploaded Blob&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fezevsynby9797f94ra72.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fezevsynby9797f94ra72.png" alt=" " width="800" height="345"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2vukcq52re6of6oc7cg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2vukcq52re6of6oc7cg.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Confirmed the uploaded file was stored correctly by inspecting its blob properties, including size, content type, access tier, and public URL — validating the file was live and accessible.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Select the uploaded blob from the container list.&lt;br&gt;
Review properties: URL, size, access tier, content type.&lt;br&gt;
Copy the blob URL to test/share public access.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating and Attaching an Amazon EBS Volume to an EC2 Instance on AWS</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Mon, 27 Jul 2026 17:26:11 +0000</pubDate>
      <link>https://dev.to/awokay/creating-and-attaching-an-amazon-ebs-volume-to-an-ec2-instance-on-aws-5fnm</link>
      <guid>https://dev.to/awokay/creating-and-attaching-an-amazon-ebs-volume-to-an-ec2-instance-on-aws-5fnm</guid>
      <description>&lt;p&gt;Step 1 — Open the EC2 Console&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flxo4u04i303ificzdwgf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flxo4u04i303ificzdwgf.png" alt=" " width="800" height="347"&gt;&lt;/a&gt;&lt;br&gt;
From the AWS EC2 dashboard, click Launch instance to begin creating a new virtual server that will later have an EBS volume attached.&lt;/p&gt;

&lt;p&gt;Step 2 — Name the Instance and Choose an AMI&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2z41ebxmnzp09ynb1y22.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2z41ebxmnzp09ynb1y22.png" alt=" " width="800" height="539"&gt;&lt;/a&gt;&lt;br&gt;
On the Launch an instance page, name the instance (e.g. "EBS-SERVER") and select an Amazon Machine Image — in this case, Amazon Linux 2023.&lt;/p&gt;

&lt;p&gt;Step 3 — Configure Key Pair and Network 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukg9clmwmhs5yq7xhi1w.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukg9clmwmhs5yq7xhi1w.png" alt=" " width="800" height="465"&gt;&lt;/a&gt;Select or create a key pair (e.g. "ebs-key") for SSH access. Under Network settings, confirm the VPC and subnet, enable auto-assign public IP, and allow SSH traffic from Anywhere (or a restricted IP range) via the security group.&lt;/p&gt;

&lt;p&gt;Step 4 — Review Storage and Launch the Instance&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftn973fm9vqdi2itqjvqp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftn973fm9vqdi2itqjvqp.png" alt=" " width="800" height="349"&gt;&lt;/a&gt;&lt;br&gt;
In Configure storage, keep the default root volume (8 GiB, gp3). Leave file systems set to None (since the EBS volume will be attached separately), review the launch summary, and click Launch instance.&lt;/p&gt;

&lt;p&gt;Step 5 — Confirm the Instance Is Running&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F76wdfo832mdk2oxrb0ca.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F76wdfo832mdk2oxrb0ca.png" alt=" " width="799" height="356"&gt;&lt;/a&gt;&lt;br&gt;
On the Instances page, confirm the new instance ("EBS-SERVER") shows a Running state with status checks passed.&lt;/p&gt;

&lt;p&gt;Step 6 — Navigate to EBS Volumes&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz4co7gwc7tz8tk3duwhk.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz4co7gwc7tz8tk3duwhk.png" alt=" " width="799" height="346"&gt;&lt;/a&gt;&lt;br&gt;
Under Elastic Block Store &amp;gt; Volumes, view existing volumes and click Create volume to provision a new EBS disk.&lt;/p&gt;

&lt;p&gt;Step 7 — Configure the New Volume&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78n0ldrbkn83y1kinrob.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78n0ldrbkn83y1kinrob.png" alt=" " width="799" height="353"&gt;&lt;/a&gt;&lt;br&gt;
Set the volume type (General Purpose SSD gp3), size (e.g. 4 GiB), IOPS, and throughput. Choose the same Availability Zone as your EC2 instance (critical — EBS volumes can only attach to instances in the same AZ), then create the volume.&lt;/p&gt;

&lt;p&gt;Step 8 — Attach the Volume via Actions Menu&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fow4hgl63mek8ps2bedy0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fow4hgl63mek8ps2bedy0.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;br&gt;
Back in the Volumes list, select the new volume's checkbox, click Actions, and choose Attach volume to link it to the running instance.&lt;/p&gt;

&lt;p&gt;Step 9 — Complete Attachment Details&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfk8wvgv7kk3zg88yhjy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfk8wvgv7kk3zg88yhjy.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;br&gt;
On the Attach volume page, confirm the Volume ID and Availability Zone match, select the target instance ("EBS-SERVER"), specify a device name (e.g. /dev/sdb), and click Attach volume.&lt;/p&gt;

&lt;p&gt;Step 10 — Connect to the Instance&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqja8cxlwdqnvn48pw1k3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqja8cxlwdqnvn48pw1k3.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;br&gt;
From the Instances page, select "EBS-SERVER" and click Connect to proceed to SSH connection setup.&lt;/p&gt;

&lt;p&gt;Step 11 — Locate the Private Key&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa9vtsuuzl5zp9sxcshkh.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa9vtsuuzl5zp9sxcshkh.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;br&gt;
In your local editor (e.g. VS Code), open the downloaded private key file ("EBS-KEY.pem") to confirm it's accessible and ready to use for the SSH connection.&lt;/p&gt;

&lt;p&gt;Step 12 — Copy and Run the SSH Command&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdve7xwlf8wszjokn7n36.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdve7xwlf8wszjokn7n36.png" alt=" " width="799" height="217"&gt;&lt;/a&gt;&lt;br&gt;
Under the SSH client tab, follow the steps to set correct key permissions (chmod 400 "EBS-KEY.pem") and copy the SSH command (e.g. ssh -i "EBS-KEY.pem" &lt;a href="mailto:ec2-user@ec2-18-232-77-8.compute-1.amazonaws.com"&gt;ec2-user@ec2-18-232-77-8.compute-1.amazonaws.com&lt;/a&gt;) to connect to the instance and verify the attached EBS volume from within the OS.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Provisioning an Amazon EFS File System and Mounting It to an EC2 Instance on AWS</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Sat, 25 Jul 2026 00:06:33 +0000</pubDate>
      <link>https://dev.to/awokay/provisioning-an-amazon-efs-file-system-and-mounting-it-to-an-ec2-instance-on-aws-22f0</link>
      <guid>https://dev.to/awokay/provisioning-an-amazon-efs-file-system-and-mounting-it-to-an-ec2-instance-on-aws-22f0</guid>
      <description>&lt;p&gt;Step 1 — Create the EFS File System&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fkfidepd8j2zxs54pky.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fkfidepd8j2zxs54pky.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;br&gt;
In the Amazon EFS console, click Create file system, name it (e.g. "kola-fs"), and select the target VPC. Review the recommended settings — Elastic throughput mode, lifecycle transitions to Infrequent Access and Archive, automatic backups, and encryption — then click Create file system.&lt;/p&gt;

&lt;p&gt;Step 2 — Confirm File System Creation&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv1wy3b76ltsmqbvgpjt5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv1wy3b76ltsmqbvgpjt5.png" alt=" " width="799" height="458"&gt;&lt;/a&gt;&lt;br&gt;
A success banner confirms the file system ("kola-fs") is Available, showing its file system ID, encryption status, size, and creation time in the File systems list.&lt;/p&gt;

&lt;p&gt;Step 3 — Launch an EC2 Instance&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F271cck7ns1k94exdrvvs.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F271cck7ns1k94exdrvvs.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;br&gt;
On the EC2 Launch an instance page, name the instance (e.g. "KOLA-SERVER"), select an Amazon Machine Image (Amazon Linux 2023), choose the instance type (t3.micro), and select or create a key pair (e.g. "EBS-KEY") for SSH access.&lt;/p&gt;

&lt;p&gt;Step 4 — Configure Storage and Attach EFS&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tilvzweu8jsreqpurco.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tilvzweu8jsreqpurco.png" alt=" " width="800" height="224"&gt;&lt;/a&gt;&lt;br&gt;
Under Configure storage, keep the default root volume settings. In the File systems section, select EFS as the file system type to attach to this instance.&lt;/p&gt;

&lt;p&gt;Step 5 — Review the EFS Network and Mount Targets&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mph7vx6j0q2wg99a5bm.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mph7vx6j0q2wg99a5bm.png" alt=" " width="799" height="419"&gt;&lt;/a&gt;&lt;br&gt;
On the EFS file system's detail page, check the Network tab to confirm mount targets are Available across each availability zone, along with their subnet IDs, IP addresses, and associated security groups — necessary for EC2 to connect.&lt;/p&gt;

&lt;p&gt;Step 6 — Configure Network Settings for the Instance&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F000b1srdxfre1axayot5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F000b1srdxfre1axayot5.png" alt=" " width="800" height="271"&gt;&lt;/a&gt;&lt;br&gt;
Back in the EC2 launch wizard, under Network settings, confirm the VPC and subnet match the EFS file system's network, enable auto-assign public IP, and configure the security group to allow inbound SSH (port 22) traffic.&lt;/p&gt;

&lt;p&gt;Step 7 — Set the File System and Mount Point&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd3o3pjd6voj0nk0428tp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd3o3pjd6voj0nk0428tp.png" alt=" " width="203" height="107"&gt;&lt;/a&gt;&lt;br&gt;
In the File systems configuration panel, select the EFS file system (kola-fs) and specify the mount point (e.g. /mnt/efs/fs1). Leave "Automatically create and attach security groups" and "Automatically mount shared file system" checked so EFS attaches on launch.&lt;/p&gt;

&lt;p&gt;Step 8 — Launch the Instance&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgxosk8qk89pgif9yp3qt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgxosk8qk89pgif9yp3qt.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;br&gt;
Review the configuration summary and click Launch instance to provision the EC2 server with the EFS file system attached.&lt;/p&gt;

&lt;p&gt;Step 9 — Confirm Successful Launch&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21ob8hg21rhaxf29h1l9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21ob8hg21rhaxf29h1l9.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;br&gt;
A success message confirms the instance launch, with a link to the new instance ID for further management.&lt;/p&gt;

&lt;p&gt;Step 10 — Open the Instance Summary&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmj8bwcy5adeki1ubazro.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmj8bwcy5adeki1ubazro.png" alt=" " width="800" height="371"&gt;&lt;/a&gt;&lt;br&gt;
On the instance details page, confirm the instance ("KOLA-SERVER") is Running, and note its public IPv4 address and public DNS. Click Connect to proceed to SSH connection setup.&lt;/p&gt;

&lt;p&gt;Step 11 — Get the SSH Connection Command&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faxrlwcpg9zsupfcnhrwa.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faxrlwcpg9zsupfcnhrwa.png" alt=" " width="799" height="373"&gt;&lt;/a&gt;&lt;br&gt;
Under the SSH client tab, follow the steps to locate your private key file, set correct permissions (chmod 400), and copy the example SSH command (e.g. ssh -i "EBS-KEY.pem" ec2-user@).&lt;/p&gt;

&lt;p&gt;Step 12 — Connect and Verify the EFS Mount&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbfw7svxsmjyzel76q68x.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbfw7svxsmjyzel76q68x.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;br&gt;
In a local terminal (e.g. VS Code), run the SSH command to connect to the instance. Once connected, run df -T to confirm the EFS file system is mounted (visible as an nfs4 filesystem type under /mnt/efs/fs1), verifying the EC2 instance has successful shared storage access.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
    </item>
    <item>
      <title>Deploying a Kubernetes Application on Azure Kubernetes Service (AKS): From Cluster Creation to Live Deployment</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Fri, 24 Jul 2026 22:21:25 +0000</pubDate>
      <link>https://dev.to/awokay/deploying-a-kubernetes-application-on-azure-kubernetes-service-aks-from-cluster-creation-to-live-3f97</link>
      <guid>https://dev.to/awokay/deploying-a-kubernetes-application-on-azure-kubernetes-service-aks-from-cluster-creation-to-live-3f97</guid>
      <description>&lt;p&gt;Step 1 — Create a Resource Group and Verify It&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foq6gytgyyabjwdhc413u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foq6gytgyyabjwdhc413u.png" alt=" " width="799" height="358"&gt;&lt;/a&gt;&lt;br&gt;
Using PowerShell, run az group create --name aks-rg --location westus3 to create a dedicated resource group for the AKS cluster. Follow up with az group list to confirm the resource group was created successfully (status: "Succeeded") alongside other existing resource groups in the subscription.&lt;/p&gt;

&lt;p&gt;Step 2 — Create the AKS Cluster&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxv9i9sr24pdmd5ofef0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxv9i9sr24pdmd5ofef0.png" alt=" " width="799" height="394"&gt;&lt;/a&gt;&lt;br&gt;
In the VS Code integrated terminal, run az aks create --resource-group aks-rg --name my-aks-cluster --node-count 1 --generate-ssh-keys to provision the Kubernetes cluster. Azure returns a detailed JSON response describing the cluster configuration, including agent pool profiles, node count, and orchestrator version.&lt;/p&gt;

&lt;p&gt;Step 3 — Verify the Cluster and Get Credentials&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgchmkwfxvhmmnuxfutrg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgchmkwfxvhmmnuxfutrg.png" alt=" " width="800" height="125"&gt;&lt;/a&gt;&lt;br&gt;
Run az aks list --output table to confirm the cluster ("my-aks-cluster") shows a Succeeded provisioning state, running Kubernetes version 1.34.6 in the westus3 region. Then run az aks get-credentials --resource-group aks-rg --name my-store-cluster to merge the cluster's credentials into your local kubeconfig for kubectl access.&lt;/p&gt;

&lt;p&gt;Step 4 — Confirm Node Connectivity&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzs5x1g7h5dm8yk171b3k.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzs5x1g7h5dm8yk171b3k.png" alt=" " width="800" height="101"&gt;&lt;/a&gt;g)&lt;br&gt;
After credentials are merged (confirmed by "Merged 'my-aks-cluster' as current context"), run kubectl get nodes to verify the cluster node is Ready and running Kubernetes version v1.34.6.&lt;/p&gt;

&lt;p&gt;Step 5 — Deploy the Application and Check Pods&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faj0havus008n2llhk4hf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faj0havus008n2llhk4hf.png" alt=" " width="800" height="387"&gt;&lt;/a&gt;&lt;br&gt;
Apply your Kubernetes manifest with kubectl apply -f my-aks.yaml, which creates the deployments and services (RabbitMQ, order-service, product-service, store-front). Run kubectl get pods to confirm all pods are Running (or initializing) as expected.&lt;/p&gt;

&lt;p&gt;Step 6 — View the Live Application&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07vrqf1w6whs02a59jbf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07vrqf1w6whs02a59jbf.png" alt=" " width="799" height="470"&gt;&lt;/a&gt;&lt;br&gt;
Navigate to the cluster's public IP in a browser to view the deployed application — in this case, a "Contoso Pet Store" storefront displaying a product catalog with images, descriptions, prices, and "Add to Cart" functionality, confirming the full stack is live and accessible.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>kubernetes</category>
      <category>automation</category>
    </item>
    <item>
      <title>Deploying and Connecting to an Ubuntu Linux VM on Azure Using SSH Public Key Authentication</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Thu, 23 Jul 2026 12:26:43 +0000</pubDate>
      <link>https://dev.to/awokay/deploying-and-connecting-to-an-ubuntu-linux-vm-on-azure-using-ssh-public-key-authentication-2gjj</link>
      <guid>https://dev.to/awokay/deploying-and-connecting-to-an-ubuntu-linux-vm-on-azure-using-ssh-public-key-authentication-2gjj</guid>
      <description>&lt;p&gt;Step 1 — Configure SSH Public Key Authentication&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0no83ijwgksonsi9bxl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0no83ijwgksonsi9bxl.png" alt=" " width="799" height="487"&gt;&lt;/a&gt;&lt;br&gt;
On the Create a virtual machine page under Administrator account, set Authentication type to SSH public key. Enter a username, leave SSH public key source as "Generate new key pair," keep the RSA SSH format, and name the key pair. Under Inbound port rules, allow selected ports and choose SSH (22), then click Review + create.&lt;/p&gt;

&lt;p&gt;Step 2 — Review and Create the VM&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pumrtc8vo9b0ylhfgq3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pumrtc8vo9b0ylhfgq3.png" alt=" " width="800" height="586"&gt;&lt;/a&gt;&lt;br&gt;
On the Review + create tab, confirm validation has passed, review the basics summary (subscription, resource group, VM name, region), and click Create to start deployment. Azure will prompt you to download the private key (.pem) at this point — save it somewhere memorable.&lt;/p&gt;

&lt;p&gt;Step 3 — Deployment in Progress&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtqvz3ht7nt2yd3582al.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtqvz3ht7nt2yd3582al.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;br&gt;
The deployment overview page shows "Deployment is in progress" while Azure provisions the network interface, network security group, and public IP address.&lt;/p&gt;

&lt;p&gt;Step 4 — Deployment Complete&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyj0plfyaaj9binbyawdi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyj0plfyaaj9binbyawdi.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
Once finished, the page updates to "Your deployment is complete." Click Go to resource, or use the linked resource group, to open the new VM.&lt;/p&gt;

&lt;p&gt;Step 5 — Open the VM and Start Connecting&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyj37b1rp88re5xowsmbv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyj37b1rp88re5xowsmbv.png" alt=" " width="800" height="497"&gt;&lt;/a&gt;&lt;br&gt;
From the VM's Overview page, review the essentials (public IP, OS, size) and click Connect to view connection options.&lt;/p&gt;

&lt;p&gt;Step 6 — View the Native SSH Command&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fav61egew1t6qbrzb8k9v.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fav61egew1t6qbrzb8k9v.png" alt=" " width="800" height="493"&gt;&lt;/a&gt;&lt;br&gt;
On the Connect page under Native SSH, Azure displays the destination VM's IP/port and a partial SSH command showing a placeholder  — a warning notes the private key file path is missing.&lt;/p&gt;

&lt;p&gt;Step 7 — Locate and Copy the Private Key Path&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwp6g16k8cp3ydluuphhl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwp6g16k8cp3ydluuphhl.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;br&gt;
In File Explorer (e.g. Downloads folder), right-click the downloaded .pem private key file and select Copy as path to grab its exact local file location.&lt;/p&gt;

&lt;p&gt;Step 8 — Paste the Key Path into Azure&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0w6mbo3rci71jzamhvas.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0w6mbo3rci71jzamhvas.png" alt=" " width="799" height="425"&gt;&lt;/a&gt;&lt;br&gt;
Back on the Connect panel, click Edit settings, paste the copied .pem file path into the "Provide a path to your SSH private key file" field, and save. Azure then assembles the complete SSH command with the key path included.&lt;/p&gt;

&lt;p&gt;Step 9 — Connect via Command 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdov32chcocwl032xqplz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdov32chcocwl032xqplz.png" alt=" " width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
Copy the completed SSH command (e.g. ssh -i "C:\Users\HomePC\Downloads\azureuser.pem" &lt;a href="mailto:azureuser@20.237.186.3"&gt;azureuser@20.237.186.3&lt;/a&gt;), paste it into Command Prompt, and press Enter to establish the SSH connection to the VM.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>"Deploying and Connecting to an Ubuntu Linux VM on Azure via Native SSH</title>
      <dc:creator>Kolarinde Awopetutimileyin</dc:creator>
      <pubDate>Thu, 23 Jul 2026 11:40:17 +0000</pubDate>
      <link>https://dev.to/awokay/deploying-and-connecting-to-an-ubuntu-linux-vm-on-azure-via-native-ssh-349o</link>
      <guid>https://dev.to/awokay/deploying-and-connecting-to-an-ubuntu-linux-vm-on-azure-via-native-ssh-349o</guid>
      <description>&lt;p&gt;Step 1 — Configure VM Basics&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcpd244ybtau87ad6hvfh.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcpd244ybtau87ad6hvfh.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;br&gt;
On the Create a virtual machine page, select your subscription and create a new resource group (named clearly, e.g. "Newkola-RG(Linux)"). Give the VM a unique name, choose your region (West US 2), leave availability/security type at default, and select Ubuntu Server 24.04 LTS – x64 Gen2 as the image. Confirm the architecture (x64) and choose a VM size that fits your workload, then select Password as the authentication type.&lt;/p&gt;

&lt;p&gt;Step 2 — Set Administrator Credentials &amp;amp; Inbound Ports&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5wgytbn1n9mxhnbw9nvi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5wgytbn1n9mxhnbw9nvi.png" alt=" " width="686" height="435"&gt;&lt;/a&gt;&lt;br&gt;
Under Administrator account, create a username and a strong password (confirm it). In Inbound port rules, choose "Allow selected ports" and select SSH (22) from the dropdown so the VM accepts SSH connections from outside.&lt;/p&gt;

&lt;p&gt;Step 3 — Review and Create the VM&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foap58abenhzwwhwkttvn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foap58abenhzwwhwkttvn.png" alt=" " width="799" height="361"&gt;&lt;/a&gt;&lt;br&gt;
On the Review + create tab, confirm validation has passed and review the estimated hourly price. Accept the marketplace terms, then click Create to begin deployment.&lt;/p&gt;

&lt;p&gt;Step 4 — Confirm Deployment&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3yw29vs4xgttujyiuwx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3yw29vs4xgttujyiuwx.png" alt=" " width="799" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once deployment finishes, the "Your deployment is complete" confirmation appears. Click Go to resource to open the newly created VM.&lt;/p&gt;

&lt;p&gt;Step 5 — Open the Connect Panel&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgag1ryfhm6yf8p5i7x4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgag1ryfhm6yf8p5i7x4.png" alt=" " width="800" height="377"&gt;&lt;/a&gt;&lt;br&gt;
From the VM's Overview page, click the Connect dropdown at the top to view available connection methods.&lt;/p&gt;

&lt;p&gt;Step 6 — Copy the SSH Command (Password Auth)&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fda8wqf4yxp3ccwqq8gw2.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fda8wqf4yxp3ccwqq8gw2.png" alt=" " width="800" height="512"&gt;&lt;/a&gt;&lt;br&gt;
On the Connect page under Native SSH, verify the destination VM's public IP and port (22), then copy the pre-built SSH command (e.g. ssh username@publicIP) and paste it into your local terminal/command prompt to connect.&lt;/p&gt;

&lt;p&gt;Step 7 — Connect Using an SSH Private Key (Alternate Method)&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8slx6ty18rmur5lyrmjv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8slx6ty18rmur5lyrmjv.png" alt=" " width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
For VMs configured with SSH key authentication, go to Connect on the VM, click Edit settings, and paste the path to your downloaded .pem private key file (e.g. C:\Users&amp;lt;user&amp;gt;\Downloads&amp;lt;key-name&amp;gt;.pem). Azure then generates the full SSH command with the key path included — copy this and run it in your local command prompt to log in.&lt;/p&gt;

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