Chapter 0
Start here
You passed AZ-104 about two years ago, so the basics are still in there. This chapter tells you what Azure changed in the meantime and gets your lab environment ready: a Linux VM with the Azure tools installed, from which you run every command in this guide.
Theory
What changed since you took the exam
The skills outline itself has not changed since October 2023. Azure has, so some things you remember are renamed or retired. If an exam question mentions a retired option, it is usually the wrong answer.
| Then | Now | Why it matters |
|---|---|---|
| Azure Active Directory (Azure AD) | Microsoft Entra ID | Same service, new name. P1/P2 licenses are now "Entra ID P1/P2". |
| Basic public IP & Basic Load Balancer | Retired (30 Sept 2025), use Standard | Standard is zone-aware and closed by default: you need an NSG to allow traffic in. |
| VMs get internet access automatically ("default outbound access") | New VNets use private subnets by default | You add explicit outbound: NAT Gateway, a load balancer outbound rule, or a public IP. You see this in chapters 3 and 6. |
| Log Analytics agent (MMA / OMS) | Azure Monitor Agent (AMA) + data collection rules | The old agent retired in August 2024. Chapter 9. |
| Unmanaged disks (VHDs in storage accounts) | Managed disks only | Unmanaged disks are retired. |
| MFA was optional for admins | MFA is mandatory for the Azure portal, CLI and PowerShell | Your lab user accounts need MFA to sign in to the portal. |
| ARM JSON templates everywhere | Bicep is the default for writing IaC | The exam asks you to read and change both. Chapter 4. |
How the labs are set up
All labs run in one resource group called rg-az104-lab in one region. Chapter 10 also uses a second region for disaster recovery. Resource names follow the Microsoft Cloud Adoption Framework abbreviations, which is also how AZ-305 expects you to think about naming.
| Prefix | Resource | Prefix | Resource |
|---|---|---|---|
rg- | Resource group | st | Storage account (no dashes allowed) |
vnet- / snet- | Virtual network / subnet | acr | Container registry (no dashes) |
nsg- / asg- | Network / application security group | log- | Log Analytics workspace |
vm- / pip- | Virtual machine / public IP | rsv- | Recovery Services vault |
lbe- / lbi- | External / internal load balancer | rt- | Route table |
Chapter 1 changes tenant-wide settings (self-service password reset, guest invitations). Don't do this in your company's production tenant. Use a personal pay-as-you-go or free-trial subscription, which comes with its own Entra tenant where you are Global Administrator.
Your Linux admin VM
Every command in this guide runs in a Bash terminal on a Linux VM that you control (your "admin workstation"). Unlike Azure Cloud Shell, it is persistent: installed tools, files, SSH keys and your saved variables are still there next time.
- The guide assumes an Ubuntu 22.04 / 24.04 LTS VM in AWS (an EC2 instance; the default user
ubuntucan runsudo). You connect to it over SSH from your laptop. - Because it lives outside Azure, it isn't touched when chapter 10 deletes
rg-az104-lab. - It has a different public IP from your browser. Chapters 7 and 8 use that: you allow only your browser's IP through a firewall, and the VM plays the "outsider" that gets blocked. You save the VM's IP as
$MYIP. - It has no desktop or browser, so you sign in to Azure with a device code (task 3).
Most of the time the lab costs little, because the VMs are tiny (Standard_B1s) and Bastion uses the free Developer tier. The resources that cost the most are the App Service plan (Standard), Site Recovery and Container Apps; each chapter tells you what to stop or delete.
- Deallocate (Stop) the VMs when you take a break between chapters. A stopped-but-not-deallocated VM still costs money.
- Chapter 2 creates a budget alert as a safety net.
- Chapter 10 ends with a full cleanup.
Lab: prepare your environment
Your values
Fill these in once. Every page then shows your names in the instructions and code blocks (the orange text). Storage accounts and registries need globally unique names, so pick 2–6 letters or digits, for example your initials plus a number.
Your storage account will be staz104xx01 and your registry acraz104xx. Pick a main region that has availability zones (all regions in this list do).
If you own a domain, chapters 3 and 8 have optional tasks that use the subdomain lab.yourdomain.com. Your main domain and its email are not touched.
-
Task
Get a Linux VM ready
Have your Ubuntu 22.04 or 24.04 LTS EC2 instance running (see Your Linux admin VM above) and connect with SSH. Its security group only needs SSH inbound from your IP; outbound to the internet must be allowed (the default). Bring its packages up to date and install the basic tools the labs use:
curl,jq,git,unzip,nanoandnslookup.Done whenlsb_release -dshows Ubuntu 22.04 or 24.04.jq --versionandnslookup -versionboth work.
Hint
nslookuplives in the packagednsutils(Ubuntu 24.04 also calls itbind9-dnsutils).Solution · Linux
sudo apt-get update && sudo apt-get -y upgrade sudo apt-get install -y curl ca-certificates gnupg lsb-release jq git unzip nano dnsutils lsb_release -d; jq --version; nslookup -version -
Task
Install the Azure tools
Install the three tools the labs depend on:
- Azure CLI (
az) from Microsoft's package repository, so thatapt upgradekeeps it current; - Bicep (chapter 4);
- AzCopy v10 (chapter 7), on your
PATH.
Done whenaz version,az bicep versionandazcopy --versionall print a version.
Hint
Microsoft publishes a one-line installer for the CLI on Debian/Ubuntu (
aka.ms/InstallAzureCLIDeb). Bicep installs through the CLI. AzCopy is a single binary in a.tar.gz.Solution · Linux
# Azure CLI (adds the packages.microsoft.com repo and installs azure-cli) curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash az version # Bicep (installed into ~/.azure/bin and used by az deployment ... -f file.bicep) az bicep install az bicep version # AzCopy v10 (on a Graviton/ARM instance use downloadazcopy-v10-linux-arm64) curl -sL https://aka.ms/downloadazcopy-v10-linux -o /tmp/azcopy.tgz tar -xzf /tmp/azcopy.tgz -C /tmp sudo install -m 755 /tmp/azcopy_linux_*/azcopy /usr/local/bin/azcopy azcopy --versionPrefer to see what the installer does first? The Install the Azure CLI on Linux page has the same steps one by one.
Later updates:
sudo apt-get update && sudo apt-get install --only-upgrade azure-cliandaz bicep upgrade. - Azure CLI (
-
Task
Sign in to your lab subscription
Sign in with the Azure CLI as the Global Administrator of your lab tenant (with MFA) and make sure the CLI points at your lab subscription.
Done when- A command shows your lab subscription's name and tenant ID.
Hint
A VM without a desktop or browser can't open the sign-in page itself. There's a sign-in flow where you enter a short code in a browser on another device.
Solution · Azure CLI
az login --use-device-code # open the shown URL in your laptop's browser and enter the code az account show --query "{name:name, id:id, tenant:tenantId}" -o table # if you have more than one subscription: # az account set --subscription "<name or id>"The sign-in is cached in
~/.azure, so you normally only do this once. If a command later says your token expired, runaz loginagain. -
Task
Register the resource providers you will need
A resource provider (like
Microsoft.Network) must be registered in a subscription before you can create its resources. Register these now so you don't have to wait later:Microsoft.App,Microsoft.ContainerInstance,Microsoft.ContainerRegistry,Microsoft.OperationalInsights,Microsoft.Insights,Microsoft.RecoveryServices,Microsoft.DataProtection,Microsoft.Web,Microsoft.AlertsManagement,Microsoft.PolicyInsights.Done when- All of them show Registered (or Registering) under Subscription → Resource providers.
Solution · Portal
Subscriptions → your subscription → Settings → Resource providers. Search each name, select it and click Register.
Solution · Azure CLI
for p in Microsoft.App Microsoft.ContainerInstance Microsoft.ContainerRegistry \ Microsoft.OperationalInsights Microsoft.Insights Microsoft.RecoveryServices \ Microsoft.DataProtection Microsoft.Web Microsoft.AlertsManagement Microsoft.PolicyInsights; do az provider register --namespace $p done az provider list --query "[?starts_with(namespace,'Microsoft.')].{ns:namespace, state:registrationState}" -o tableExam trap"Deployment fails with The subscription is not registered to use namespace X." The fix is to register the resource provider, not to change RBAC roles or quotas.
-
Task
Save your lab variables for good
Save the block below in a file
~/az104.envand make every new terminal load it automatically. It also stores the VM's public IP as$MYIPand creates a working folder~/az104.RG=rg-az104-lab LOC=westeurope LOC2=northeurope INIT=xx ST=staz104${INIT}01 ACR=acraz104${INIT} MYIP=$(curl -s https://api.ipify.org)Done when- In a new terminal,
echo $RG $ST $MYIPprints your values and an IP address.
Solution · Linux
cat > ~/az104.env <<'EOF' RG=rg-az104-lab LOC=westeurope LOC2=northeurope INIT=xx ST=staz104${INIT}01 ACR=acraz104${INIT} MYIP=$(curl -s https://api.ipify.org) EOF echo '[ -f ~/az104.env ] && . ~/az104.env' >> ~/.bashrc mkdir -p ~/az104 . ~/az104.env; echo $RG $ST $MYIPEach lab still starts with a short variable block. Pasting it again is harmless; it's there in case you skipped this step or work in another shell.
- In a new terminal,
Your Linux VM has the Azure CLI, Bicep and AzCopy, you are signed in, the providers are registered, and your values load in every terminal. Nothing has been created in Azure yet, so this costs nothing.