Building in the cloud often feels like magic, until you hit your first Deployment Failed error. Whether it’s a regional quota limit or a firewall blocking your path, the journey from your local terminal to a live web server is rarely a straight line.
In this article, I am taking you behind the scenes of my latest lab. We will move past the common hurdles, like regional capacity limits: by pivoting our deployment strategy, mastering the Azure CLI to build a fresh infrastructure, and using SSH one-liners to transform a blank Ubuntu instance into a live Nginx web server.
If you have ever wondered how to bridge the gap between your laptop and a powerful Azure VM while navigating real-world troubleshooting, this guide is for you.
Let's get to it!
Phase 1: Install Azure CLI & Login. We will install the Azure CLI on your machine and authenticate to your Azure subscription.
Action plan:
STEP 1: When you start a project the first thing to do is create a new directory
Open Linux Server Visual Studio Code, go to File and navigate dropdown. Click on open folder.
STEP 2: Click on New folder to create a folder. Rename folder Linux server, select the linux folder and save. Everything Linux we are handling will be saved in the folder.
STEP 3: We will be using terminal most of the time. To get to terminal click on view and process to click on the terminal icon in the dropdown
STEP 4: We are going to install Azure Cli in our terminal window. Go to your Google browser and open a new tab. Type and search for Azure cli. Proceed to install application
STEP 5: Select Microsoft installer (MSI) with powershell and locate PowerShell (winget install --exact --id Microsoft.AzureCLI), Copy the command
STEP 6: Scroll down and copy the installation command.
STEP 7: Proceed to paste command in Terminal and click enter to run command. Verify version installed by typing az -- version and click enter.
STEP 8: Once confirmation report is retrieved, proceed to login. Type
az login and click enter. Select account you want to login with.
STEP 9: Confirm your Azure subscription. I have just one active subsrcription, so I will write 1 and click enter
Phase 2: Create a Resource Group. This resource group is to act as the logical container for your entire lab environment.
Action plan:
STEP 1: We will proceed to set Environment variables. This environment variable is like a labeled box that holds a specific piece of information. Instead of your code needing to know exactly what is inside the box, it simply calls out the label on the box (the variable name). The system then opens the box and provides whatever value is currently kept inside. We will proceed to run the commands below in the terminal to condition our environment variable .
- RG="azurecli-lab-rg : This sets the shell variable RG so later commands can reference it with $RG.
- LOCATION="eastus" : Sets the shell variable LOCATION so later commands can reference it with $LOCATION.
- az group create --name $RG --location $LOCATION : Creates a resource group called "$RG" — a logical container for all the Azure resources in this lab.
- az group show --name $RG : Runs the Azure CLI command "az group show" — see "az group show --help" for details.
Phase 3: We will build a Virtual Network (VNet) & Subnet. Creating a secure private network for your Azure resources to communicate on.
Action plan:
Step 1 : Run this command in the terminal: az network vnet create --address-prefix 10.0.0.0/16 --resource-group $RG --name lab-vnet --location $LOCATION . This creates a Virtual Network (VNet) — the private network your Azure resources communicate on.
Step 2 : Create a Subnet. This carves out a smaller 10.0.1.0/24 piece (subnet) of the VNet specifically for your VMs. Segmenting networks allows you to apply different routing and firewall rules to different types of resources. We will proceed to run this command in the terminal: az network vnet subnet create --resource-group $RG --vnet-name lab-vnet --name lab-subnet --address-prefix 10.0.1.0/24. Check your Microsoft Azure portal to confirm creation of the lab-vnet
Step 3 : Create a Network Security Group (NSG), which acts as a virtual firewall. Without an NSG attached, Microsoft allows no inbound traffic but allows all outbound traffic. We need an NSG to poke specific holes in the firewall. We will proceed to run this command in the terminal: az network nsg create --resource-group $RG --name lab-nsg
Step 4 : Open port 22 (SSH) & 80 (HTTP). This adds inbound rules prioritizing SSH (port 22) and HTTP (port 80) access from the internet. We will need SSH to log in and configure the server, and HTTP so users can view the web page. Let us proceed to run this command in the terminal: az network nsg rule create --resource-group $RG --nsg-name lab-nsg --name AllowHTTP --priority 1010 --destination-port-ranges 80 --access Allow --protocol Tcp --direction Inbound
Step 5: Attach NSG to Subnet. Enforces the firewall rules (NSG) at the subnet boundary. Applying the NSG to the subnet ensures that any VM created in that subnet automatically inherits those exact firewall rules — protecting the entire subnet. Let us proceed to run this command in the terminal: az network vnet subnet update --resource-group $RG --vnet-name lab-vnet --name lab-subnet --network-security-group lab-nsg. You can run your code in a straight line or use the backtick (located under the Esc key) at the end of every line except the last one. Like this **az network vnet subnet update
--resource-group $RG
--vnet-name lab-vnet
--name lab-subnet
--network-security-group lab-nsg
Note: If you encounter errors, run the command again and ensure it is entered correctly.
Phase 4: We will provision a Linux Virtual Machine. Creating an Ubuntu VM with a public IP inside our VNet.
Action plan:
Step 1 : Allocate a Public IP. This allocates a static public IP address in Azure. Without a public IP, the VM can only be accessed internally through the VNet or a VPN. You need this to reach your web server from your browser. Run this command in the terminal: az network public-ip create --resource-group $RG --name lab-public-ip --allocation-method Static --sku Basic
From the error above, essentially, Azure is telling us that for our specific subscription and region, the limit for Basic SKU Public IPs is currently set to zero. Additionally, Microsoft is phasing out the Basic SKU in favor of the Standard SKU for better security and performance.
The Fix
To bypass this error, we will need to change the --sku to Standard. In Azure, a Standard SKU Public IP must also use the Static allocation method (it does not support Dynamic).
Run this command instead: az network public-ip create --resource-group $RG --name lab-public-ip --allocation-method Static --sku Standard
or
az network public-ip create
--resource-group $RG
--name lab-public-ip
--allocation-method Static
--sku Standard
Step 2 :Create the VM. This creates a B1s Ubuntu VM with auto-generated SSH keys and connects it to the existing subnet and firewall. This is the actual cloud compute instance that will run our web application code. Run this command: az vm create --resource-group azurecli-lab-rg --name lab-vm --image Ubuntu2204 --size Standard_B2s_v2 --location koreacentral --admin-username azureuser --generate-ssh-keys --vnet-name lab-vnet --subnet lab-subnet --public-ip-address lab-public-ip --nsg lab-nsg
Note: When I first tried to deploy my VM in East US, I received a red wall of text:
The requested VM size 'Standard_B1s' is currently not available in location 'East US' for this subscription.
What happened?
Cloud regions are essentially giant parking lots. Sometimes, the compact car spots (like the B1s or B2s sizes) are completely full in a specific region.
The Fix: We will pivot to Korea Central (koreacentral), a region that has plenty of space for my VM size.
Run this command in the terminal:
- $RG="azurecli-lab-rg" - Set the Variable
- az network nsg create --resource-group $RG --name lab1-nsg --location koreacentral - To create the Security Group
- az network vnet create --resource-group $RG --name lab1-vnet --location koreacentral --subnet-name lab1-subnet- Create the Virtual Network.
- az vm create --resource-group $RG --name lab1-vm --image Ubuntu2204 --size Standard_B2s_v2 --location koreacentral --admin-username azureuser --generate-ssh-keys --vnet-name lab1-vnet --subnet lab1-subnet --public-ip-address lab1-public-ip --nsg lab1-nsg - The Final Deployment.
Step 3 : Retrieve the public IP. Filters the Azure API response to return just the IP address string. We will need this IP to SSH into the machine and to test the web application. Run this command in the terminal: az network public-ip show --resource-group $RG --name lab1-public-ip --query ipAddress --output tsv
Step 4 : Verify the VM is running. This queries the VM status and displays it in a clean table format. Always verify provisioning success before attempting connections. Run this command in the terminal: az vm show --resource-group $RG --name lab1-vm --show-details --query '{Name:name, State:powerState, IP:publicIps}' --output table
Step 5 : SSH into your VM & install Nginx. Logs into the VM over the internet via SSH, installs the Nginx package using APT, and starts the service. A fresh VM is blank. Nginx serves as the web server to test our HTTP port 80 firewall rule. Run this command in the terminal:
ssh -i ~/.ssh/id_rsa azureuser@
sudo apt update && sudo apt install nginx -y
sudo systemctl enable nginx && sudo systemctl start nginx
The Connection timed out error in our latest screenshot indicates that while our VM is running, our terminal cannot reach it over port 22. This is almost certainly because the Network Security Group (NSG) for our new lab1 infrastructure does not yet have a rule allowing SSH traffic.
Think of the NSG as a locked door; even if the server is "home," you can't get in unless you specifically authorize the port.
The Fix: Open Port 22
Run this command to tell Azure to allow SSH connections into our lab1-nsg; az network nsg rule create --resource-group $RG --nsg-name lab1-nsg --name AllowSSH --priority 1000 --destination-port-ranges 22 --access Allow --protocol Tcp --direction Inbound
We will now SSH into our VM to remotely install and configure Nginx. Run this command: ssh -i ~/.ssh/id_rsa azureuser@20.214.200.240 "sudo apt update && sudo apt install nginx -y && sudo systemctl start nginx"
Conclusion: Since our terminal shows the installation is done, let's head over to Chrome to do a final verification. First we have to allow access
by running this final command in the terminal: az network nsg rule create --resource-group $RG --nsg-name lab1-nsg --name AllowHTTP --priority 1010 --destination-port-ranges 80 --access Allow --protocol Tcp --direction Inbound
Proceed to Open Chrome. Paste the IP address: http://20.214.200.240. The Result: You should see a white page with bold text saying "Welcome to nginx!".
MISSION ACCOMPLISHED!
































Top comments (7)
Great job
Nice
Your works are usually so clean 👌🏽🙌🏽
Well done.
Thank you so much, Boss😁🙏
🙌🏽
Some comments may only be visible to logged-in visitors. Sign in to view all comments.