Home › Practice Tools › Azure CLI Practice Simulator
๐Ÿ–ฅ๏ธ
Azure ยท Hands-On CLI

Azure CLI Practice Simulator

Hands-on practice with real "az" CLI syntax in a fully offline sandbox - create resource groups, spin up VMs, add storage accounts, then list/start/stop/delete them. No real subscription or login required. Save and share your session.
Ideal for: Azure learners who want real "az" CLI muscle memory before touching a billed subscription.

What you'll practice

Start practicing

Azure CLI Practice Simulator is part of Practice Tools. Sign in or create an account, then subscribe for โ‚ฆ4,000/month to unlock it.

๐Ÿ“‹ Lab Instructions

Step-by-step exercises for Azure CLI Practice Simulator - read them here, then practice live in the tool above.

Beginner

Last updated: August 22, 2026
Beginner Lab โ€” Azure CLI Practice Simulator
shell: bash โ€” az CLI 2.6x โ€” connected lab1-beginner.sh
Beginner Practice Tool โ€” Lab Instructions

Getting comfortable in the Azure CLI

Your first hands-on pass through the Azure CLI Practice Simulator โ€” logging in, understanding subscriptions, and managing your first resource group. No prior Azure experience required.

โฑ ~40 min ๐ŸŽฏ 9 commands ๐Ÿงฐ No prior Azure experience required

Objectives

  • Authenticate with az login and understand what a subscription is.
  • Read command output and understand --output formats (table, json).
  • Create, inspect, and delete a resource group.
  • Use az --help and command completion to explore the CLI safely.

Prerequisites

  • A free CRMNuggets account (to launch and save the simulator session).
  • Basic comfort typing in a terminal โ€” no Azure knowledge assumed.
Cmd 1:
Launch the simulator and check the CLI version
az --version

Confirms the simulated CLI is installed and shows which extensions are loaded, just like a real terminal.

Result:

โœ“ Checkpoint โ€” a version table prints with azure-cli at the top.

Cmd 2:
Log in to the simulated environment
az login

In the simulator this completes instantly with a demo account โ€” in real Azure it opens a browser window to sign in.

Result:

โœ“ Checkpoint โ€” a JSON array prints listing at least one subscription with "isDefault": true.

Cmd 3:
Check which account and subscription is active
az account show --output table

The --output table flag reformats the same data into a human-readable table instead of raw JSON.

Result:

โœ“ Checkpoint โ€” you can name your subscription's ID and state (Enabled) from the table.

Cmd 4:
List available regions
az account list-locations --output table

Scroll the output and pick a region close to you (for example westeurope or southafricanorth) to use for the rest of this lab.

Result:

โœ“ Checkpoint โ€” you've written down one region name to reuse in later commands.

Cmd 5:
Create your first resource group
az group create --name myFirstRG --location westeurope

A resource group is a container that holds related Azure resources โ€” almost everything you create later must belong to one.

Result:

โœ“ Checkpoint โ€” JSON prints with "provisioningState": "Succeeded".

Cmd 6:
List and filter resource groups
az group list --output table
az group list --query "[?name=='myFirstRG']"

The --query flag uses JMESPath to filter results โ€” a core CLI skill you'll reuse constantly.

Result:

โœ“ Checkpoint โ€” the filtered query returns exactly one result matching myFirstRG.

Cmd 7:
Trigger and read a CLI error
az group show --name doesNotExistRG

Read the error message closely โ€” it names the missing resource and a status code, the same pattern every Azure error follows.

Result:

โœ“ Checkpoint โ€” you can explain, in one sentence, what the error told you and why it happened.

Cmd 8:
Explore help without breaking anything
az group --help
az group create --help

Run these before trying an unfamiliar command in later labs โ€” it's faster than searching online and always matches your installed version.

Result:

โœ“ Checkpoint โ€” you can name two flags az group create accepts besides --name and --location.

Cmd 9:
Clean up your resource group
az group delete --name myFirstRG --yes --no-wait

--yes skips the confirmation prompt and --no-wait returns control immediately instead of blocking until deletion finishes.

Result:

โœ“ Lab complete โ€” running az group list --output table a minute later no longer shows myFirstRG.

Troubleshooting

Command hangs with no outputSome commands block until the operation finishes. Add --no-wait or wait โ€” the simulator will time out safely after a minute.
"Please run az login" keeps appearingYour simulated session expired. Re-run az login to refresh it.
Output is unreadable raw JSONAppend --output table to almost any command for a cleaner view.
--query returns nothingCheck quoting โ€” JMESPath expressions need to be wrapped in quotes matching your shell.

Completion checklist

You've logged in, created and inspected a resource group, filtered results with --query, and deleted the resource group cleanly.

Intermediate

Last updated: August 22, 2026
Intermediate Lab โ€” Azure CLI Practice Simulator
shell: bash โ€” az CLI 2.6x โ€” connected lab2-intermediate.sh
Intermediate Practice Tool โ€” Lab Instructions

Standing up real infrastructure

Provision a virtual machine, a storage account, and basic networking, then chain commands together with variables and JMESPath queries the way you would in a real deployment script.

โฑ ~75 min ๐ŸŽฏ 9 commands ๐Ÿงฐ Comfortable with resource groups and basic CLI flags

Objectives

  • Create a virtual network, subnet, and network security group.
  • Deploy a virtual machine and a storage account into that network.
  • Chain commands using shell variables and --query output.
  • Open a port safely and verify connectivity settings before moving on.

Prerequisites

  • Completion of the Beginner lab, or equivalent CLI familiarity.
  • Basic networking concepts: what a subnet and a public IP are.
Cmd 1:
Create a resource group for this lab
az group create --name labInfraRG --location westeurope
Result:

โœ“ Checkpoint โ€” "provisioningState": "Succeeded" in the JSON response.

Cmd 2:
Create a virtual network and subnet
az network vnet create --resource-group labInfraRG \
  --name labVnet --address-prefix 10.0.0.0/16 \
  --subnet-name labSubnet --subnet-prefix 10.0.0.0/24
Result:

โœ“ Checkpoint โ€” the response includes a subnets array with labSubnet listed.

Cmd 3:
Create a storage account and store its key in a variable
az storage account create --resource-group labInfraRG \
  --name labstorage$RANDOM --sku Standard_LRS

Storage account names must be globally unique โ€” appending $RANDOM avoids a naming collision in the shared simulator environment.

Result:

โœ“ Checkpoint โ€” JSON shows "statusOfPrimary": "available".

Cmd 4:
Deploy a virtual machine into your subnet
az vm create --resource-group labInfraRG --name labVM \
  --image Ubuntu2204 --vnet-name labVnet \
  --subnet labSubnet --admin-username azureuser \
  --generate-ssh-keys

This is the slowest command in the lab โ€” the simulator mimics real Azure provisioning time.

Result:

โœ“ Checkpoint โ€” the response includes a publicIpAddress field with a non-empty value.

Cmd 5:
Capture the VM's public IP into a variable
IP=$(az vm show --resource-group labInfraRG --name labVM \
  --show-details --query publicIps --output tsv)
echo $IP

--output tsv strips quotes and formatting, making a value safe to store directly in a shell variable.

Result:

โœ“ Checkpoint โ€” echo $IP prints a plain IP address with no surrounding quotes.

Cmd 6:
Open a port for SSH access
az vm open-port --resource-group labInfraRG --name labVM \
  --port 22 --priority 1001

Opening a port creates a network security group rule โ€” in production, always scope this to a specific source IP range, not *.

Result:

โœ“ Checkpoint โ€” the returned NSG rule shows "access": "Allow" and "destinationPortRange": "22".

Cmd 7:
List every resource in the group at a glance
az resource list --resource-group labInfraRG \
  --query "[].{Name:name, Type:type}" --output table
Result:

โœ“ Checkpoint โ€” the table lists at least the VM, vnet, storage account, and NSG.

Cmd 8:
Tag resources for cost tracking
az vm update --resource-group labInfraRG --name labVM \
  --set tags.environment=lab tags.owner=you

Tags don't change how a resource behaves โ€” they exist purely to organize and filter resources later, especially for billing reports.

Result:

โœ“ Checkpoint โ€” az vm show now includes both tags under a "tags" object.

Cmd 9:
Tear down the whole environment in one command
az group delete --name labInfraRG --yes --no-wait

Deleting the resource group removes the VM, vnet, storage account, and NSG together โ€” the same "blast radius" logic real teams rely on for cleanup.

Result:

โœ“ Lab complete โ€” az group list no longer shows labInfraRG once deletion finishes.

Troubleshooting

VM creation fails with a name conflictAnother session may already use that VM or storage name. Add a random suffix and retry.
$IP is emptyThe VM may still be provisioning. Re-run az vm show after a short wait.
Port-open command errors on priorityNSG rule priorities must be unique per network security group; try a different number like 1002.
Tags don't appearConfirm you used tags.key=value pairs, not a single tags="..." string.

Completion checklist

A VM is deployed inside your custom vnet, SSH is reachable via an opened port, resources are tagged, and the resource group deletes cleanly in one command.

Expert

Last updated: August 22, 2026
Advanced Lab โ€” Azure CLI Practice Simulator
shell: bash โ€” az CLI 2.6x โ€” connected lab3-advanced.sh
Advanced Practice Tool โ€” Lab Instructions

Infrastructure as code and automation

Deploy infrastructure from a Bicep template, manage access with RBAC, automate a recurring task, and query monitoring data โ€” the workflow real cloud teams run day to day.

โฑ ~110 min ๐ŸŽฏ 10 commands ๐Ÿงฐ Comfortable with VMs, networking, and JMESPath queries

Objectives

  • Deploy resources declaratively from a Bicep template instead of individual commands.
  • Assign a role to a user or service principal with least-privilege scoping.
  • Create a service principal for unattended, scripted automation.
  • Query Azure Monitor metrics and export a deployment as reusable code.

Prerequisites

  • Completion of the Intermediate lab, or equivalent experience provisioning VMs and networking.
  • Basic familiarity with JSON/YAML-style configuration files.
Cmd 1:
Create a resource group for this lab
az group create --name labIacRG --location westeurope
Result:

โœ“ Checkpoint โ€” "provisioningState": "Succeeded" in the response.

Cmd 2:
Inspect the provided Bicep template
cat main.bicep

The simulator preloads main.bicep, which declares a storage account and an App Service plan. Read it before deploying โ€” declarative infrastructure should always be reviewed like code, because it is code.

Result:

โœ“ Checkpoint โ€” you can name the two resource types the template will create.

Cmd 3:
Validate before deploying
az deployment group validate --resource-group labIacRG \
  --template-file main.bicep

validate checks the template and parameters without creating anything โ€” always run it before a real deployment.

Result:

โœ“ Checkpoint โ€” the command returns no errors and reports the template is valid.

Cmd 4:
Deploy the template
az deployment group create --resource-group labIacRG \
  --template-file main.bicep --name labDeployment
Result:

โœ“ Checkpoint โ€” "provisioningState": "Succeeded", and both resources from the template now exist in the group.

Cmd 5:
Create a service principal for automation
az ad sp create-for-rbac --name labAutomationSP \
  --role Contributor \
  --scopes /subscriptions/<subscription-id>/resourceGroups/labIacRG

Scoping the role to a single resource group, not the whole subscription, is the least-privilege pattern used in real CI/CD pipelines.

Result:

โœ“ Checkpoint โ€” the output includes appId, password, and tenant โ€” save these securely, they print only once.

Cmd 6:
Confirm the role assignment
az role assignment list --assignee labAutomationSP \
  --resource-group labIacRG --output table
Result:

โœ“ Checkpoint โ€” a row shows role Contributor scoped to labIacRG only.

Cmd 7:
Schedule an automated task
az vm auto-shutdown --resource-group labIacRG --name labVM \
  --time 1900

Auto-shutdown schedules are a simple, common cost-control automation โ€” this same pattern extends to Logic Apps and Automation Runbooks for more complex jobs.

Result:

โœ“ Checkpoint โ€” the response confirms a shutdown schedule at 19:00.

Cmd 8:
Query monitoring metrics
az monitor metrics list --resource labstorage \
  --resource-group labIacRG \
  --resource-type Microsoft.Storage/storageAccounts \
  --metric "UsedCapacity"
Result:

โœ“ Checkpoint โ€” a time series of data points prints, even if usage is currently near zero.

Cmd 9:
Export the live resource group back to a template
az group export --name labIacRG --output json > exported-template.json

Exporting existing resources into a template is how teams bring manually created infrastructure under version control after the fact.

Result:

โœ“ Checkpoint โ€” exported-template.json exists and contains a "resources" array.

Cmd 10:
Revoke access and tear down
az ad sp delete --id labAutomationSP
az group delete --name labIacRG --yes --no-wait

Always revoke service principal credentials before deleting the resources they were scoped to โ€” cleaning up in the wrong order can leave orphaned credentials.

Result:

โœ“ Lab complete โ€” the service principal no longer appears in az ad sp list, and the resource group is gone.

Troubleshooting

Bicep validate fails on parametersCheck main.bicep for required parameters and pass them with --parameters key=value.
create-for-rbac permission deniedYour simulated account needs Owner or User Access Administrator rights at the target scope โ€” narrow the --scopes value and retry.
Auto-shutdown time rejectedUse 24-hour HHMM format with no colon, e.g. 1900 not 19:00.
Metrics query returns emptyNew resources can take a few minutes before metrics populate โ€” retry shortly after creation.

Completion checklist

Infrastructure deployed from Bicep, a scoped service principal created and later revoked, an automated shutdown scheduled, and the live environment exported back to a template.