Deploying Azure Virtual Desktop for a client, start to finish
6 min readMarkdown version
Register the resource provider, prepare identity and networking, then create the workspace, the host pool, and the application group that references the host pool, in that order. Session hosts come next: each needs a registration token that exists before the AVD agent installs, a network interface, an osProfile with admin credentials, and an image reference. Assign users to the application group, then add a scaling plan, which requires the AVD service principal to already have access to the host pool.
The dependency chain is the whole difficulty
AVD is not one resource, it is a small graph of them, and each edge is a hard ordering constraint. The workspace has to exist before an application group is published into it. The application group references the host pool by its full ARM path at creation, so the pool has to exist first. A session host cannot register without a registration token that the host pool issues, and the token has to exist before the AVD agent installs, not after.
Doing this by hand once is fine. Doing it for every new client, identically, months apart, is what templates are for.
Template mistakes that fail against real ARM
When we validated our own AVD templates against a live subscription with az deployment group validate on 2026-07-01, four requirements produced hard failures rather than warnings. They are worth knowing because they are easy to get wrong in a hand-written template and the error text is not always obvious.
- osProfile is mandatory: A Microsoft.Compute/virtualMachines resource provisioning from a generalized image must carry osProfile with adminUsername and adminPassword. Without it, validation fails.
- At least one network interface: networkProfile.networkInterfaces must reference a NIC. A session host with no NIC is rejected.
- Image reference is either or: storageProfile.imageReference takes either an id, for a Compute Gallery version, or the publisher, offer, sku and version quartet for a marketplace image. Supplying both is invalid.
- Scaling plan thresholds: A schedule missing rampUpCapacityThresholdPct is a live 400. Both ramp-up and ramp-down thresholds are required, each between 1 and 100.
Choosing images
The multi-session marketplace images live under publisher MicrosoftWindowsDesktop. The offer windows-11 carries the plain multi-session SKUs, and the offer office-365 carries the variants with Microsoft 365 Apps preinstalled, which saves a long application install step on every host.
Custom images belong in an Azure Compute Gallery once a client needs anything beyond the marketplace build. Referencing a gallery version by id is the same template with a different image reference, which is why keeping the image choice as a template parameter rather than a hard-coded value matters more than it looks.
What to check before handing it to the client
A deployment that provisions cleanly can still be wrong in ways only a real user finds. Connect from outside the client's network as an assigned user, not as yourself with elevated rights. Sign out and back in on a different host to prove the profile roams. Force a ramp-down and confirm hosts reach Deallocated, because a host pool that scales down into Stopped rather than Deallocated is still costing full price.
Microsoft also recommends keeping round-trip latency from the client network to the host pool region under 150 ms, which is worth measuring from the client's actual office rather than assuming from the map.
Doing it the same way every time
rugged.sh ships this as versioned, parameterized templates wrapped in Azure Deployment Stacks, so a client deployment is a form rather than a runbook, and the resources it created stay identifiable and protected afterwards. The deployment runs as a durable, idempotent job you can watch to completion rather than a script that fails halfway and leaves you guessing.
Deploy Azure Virtual Desktop for a customer tenant
The dependency order for a first AVD deployment in a customer's Azure subscription, from resource provider registration to a scaling plan.
Register the resource provider
Register Microsoft.DesktopVirtualization on the target subscription. This requires the */register/action permission, which Contributor and Owner include.
Settle identity
Decide whether session hosts join Microsoft Entra ID directly or an AD DS or Entra Domain Services domain. Users must exist in the Entra tenant, and hybrid identities must match on UPN or SID. The account used to join a domain cannot have MFA enabled.
Prepare networking
Create the virtual network and subnet in the same region as the session hosts, with line of sight to domain controllers and DNS if domain joining. No inbound ports are required: sessions establish a reverse connection outbound over TCP 443.
Create the workspace
Create the AVD workspace first. Application groups are published into it, so it must exist before the objects that reference it.
Create the host pool
Choose pooled multi-session or personal, and set the load balancing and maximum session limit. The host pool issues the registration tokens session hosts use to join.
Create and register the application group
The application group references the host pool by its full ARM resource path at creation time, then is registered to the workspace. Assign the Desktop Virtualization User role to the group of users who should see the resource.
Deploy session hosts
Each session host VM needs a network interface, an osProfile with admin username and password to provision from a generalized image, and a storageProfile image reference. Take a registration token before the AVD agent installs; the token must already exist when the agent runs.
Configure profiles
Set up FSLogix profile containers on Azure Files or Azure NetApp Files. With Entra-joined hosts, profile storage requires hybrid identities synchronized from AD DS.
Add a scaling plan
Create the scaling plan and assign it to the host pool. Every schedule needs both a ramp-up and a ramp-down capacity threshold between 1 and 100, and the AVD service principal needs access to the host pool before the plan can act on it.
Validate before you hand over
Connect as a real assigned user from an external network, confirm profiles roam, force a ramp-down and confirm hosts reach Deallocated rather than Stopped.
Questions people ask
- What order do AVD resources have to be created in?
- Workspace, then host pool, then application group, which references the host pool by its ARM path at creation and is then registered to the workspace. Session hosts follow, each needing a registration token issued by the host pool before the AVD agent installs. Scaling plans come last.
- Do I need to open inbound ports for Azure Virtual Desktop?
- No. Microsoft documents that users establish a reverse connection to the service, so no inbound ports are required. Connections use TCP 443 by default, with RDP Shortpath able to establish a direct UDP transport on managed or public networks.
- Why does my AVD scaling plan fail to create?
- The most common causes are a schedule missing its ramp-up or ramp-down capacity threshold, which is a hard 400 from ARM, and the Azure Virtual Desktop service principal not having been granted access to the host pool the plan references.
- Can I deploy AVD into a customer tenant without Global Administrator?
- Yes. Deployment happens in the customer's Azure subscription, so it needs Azure RBAC on that subscription rather than a directory-wide admin role. rugged.sh onboards a customer with one scoped app registration plus Owner on the subscription, and never asks for standing Global Administrator.
Sources
Microsoft's behaviour described above was read from these pages on the dates shown. Claims that come from our own testing against a live Azure subscription carry that date inline.
- Microsoft Learn: Prerequisites for Azure Virtual Desktop (read September 10, 2026)
- Microsoft Learn: Autoscale scaling plans for Azure Virtual Desktop (read September 10, 2026)