Mastering Azure Virtual Desktop: A Comprehensive Setup Guide for SMBs

In today's dynamic business landscape, enabling secure, flexible remote work is no longer a luxury but a necessity for Small and Medium-sized Businesses (SMBs). Traditional on-premises desktop infrastructure often struggles with scalability, security, and cost-efficiency. This is where Azure Virtual Desktop (AVD) shines. As your trusted Montreal-based IT consultants at SkyCore Solutions, we've crafted this comprehensive Azure Virtual Desktop setup guide to empower your SMB to deploy a robust, secure, and scalable virtual desktop infrastructure on Azure.
By the end of this guide, you will have a fully functional Azure Virtual Desktop environment, enabling your team to access their Windows 11 multi-session desktops and applications from anywhere, on any device, significantly reducing IT overhead and enhancing productivity.
Prerequisites
- Azure Subscription: An active Azure subscription. The account used for initial deployment requires at least the
ContributororOwnerrole on the subscription or target resource group. - Licensing: Each user requires an eligible Microsoft 365 or Windows license. For Windows 11/10 Enterprise multi-session, this includes:
Microsoft 365 Business Premium,Microsoft 365 E3/E5,Microsoft 365 A3/A5,Windows E3/E5, orWindows A3/A5. For Windows Server, a Client Access License (CAL) may be required. - Identity Provider: Azure Active Directory (now Microsoft Entra ID). Session hosts must be domain-joined to an Active Directory Domain Services (AD DS) or Microsoft Entra ID. For SMBs, hybrid join to an existing on-premises AD DS synchronized with Microsoft Entra ID is common, or pure Microsoft Entra join for cloud-native deployments.
- Tools:
- Azure CLI (latest version, installed locally or via Azure Cloud Shell)
- Azure PowerShell (Az module, installed locally or via Azure Cloud Shell)
- Networking: Basic understanding of Azure Virtual Networks (VNets), subnets, and Network Security Groups (NSGs).
- Estimated Cost: While AVD optimizes costs with multi-session, anticipate infrastructure costs (VMs, storage, networking) starting from approximately $200-$500 USD/month for a small team, excluding user licenses. Costs scale with usage and VM size.
Step 1: Prepare Azure Subscription and Resource Group
Before deploying any resources, ensure your Azure subscription is ready for Azure Virtual Desktop and create a dedicated resource group to logically organize your AVD components. This makes management and cost tracking much easier.
az provider register --namespace Microsoft.DesktopVirtualization
az group create --name "avd-rg-skycore-prod" --location "canadacentral"
az provider register --namespace Microsoft.DesktopVirtualization: Registers the necessary Azure resource provider for Azure Virtual Desktop in your subscription. This is a one-time operation.az group create --name "avd-rg-skycore-prod" --location "canadacentral": Creates a new resource group namedavd-rg-skycore-prodin theCanada Centralregion. We recommend this region for our Montreal-based clients for proximity and latency benefits.
Portal alternative:
- Sign in to the Azure portal.
- Search for "Subscriptions", select your subscription.
- Under "Settings", click "Resource providers". Search for
Microsoft.DesktopVirtualizationand click "Register" if its status is "NotRegistered". - Search for "Resource groups", then click "+ Create". Fill in "Subscription", "Resource group name" (e.g.,
avd-rg-skycore-prod), and "Region" (e.g.,Canada Central), then review and create.
Run this to verify:
az provider show --namespace Microsoft.DesktopVirtualization --query registrationState
az group show --name "avd-rg-skycore-prod" --query name
Step 2: Set Up Azure Virtual Network (VNet)
Your Azure Virtual Desktop session hosts require a virtual network to communicate with each other, your users, and any on-premises resources (if applicable). This VNet will host your session host VMs and typically connects to your identity provider.
az network vnet create \
--name "avd-vnet-skycore" \
--resource-group "avd-rg-skycore-prod" \
--location "canadacentral" \
--address-prefixes "10.0.0.0/16"
az network vnet subnet create \
--name "avd-subnet" \
--vnet-name "avd-vnet-skycore" \
--resource-group "avd-rg-skycore-prod" \
--address-prefixes "10.0.1.0/24"
az network vnet create: Creates a new virtual network namedavd-vnet-skycorewith an address space of10.0.0.0/16.az network vnet subnet create: Creates a subnet namedavd-subnetwithin the VNet, dedicated for your AVD session hosts, with an address prefix of10.0.1.0/24.
Portal alternative:
- Search for "Virtual networks", click "+ Create".
- Select your "Subscription" and "Resource group". Give it a "Name" (e.g.,
avd-vnet-skycore) and "Region" (e.g.,Canada Central). Configure "IP Address" space (e.g.,10.0.0.0/16). - On the "Subnets" tab, click "+ Add subnet". Name it (e.g.,
avd-subnet) and define the "Subnet address range" (e.g.,10.0.1.0/24). Review and create.
Run this to verify:
az network vnet show --name "avd-vnet-skycore" --resource-group "avd-rg-skycore-prod" --query subnets[].name
For maximum efficiency and the best user experience, always choose an Azure Gallery image optimized for Azure Virtual Desktop. For SMBs,
Windows 11 Enterprise multi-session + Microsoft 365 Apps (or a similar optimized Windows 10 image) is highly recommended. This allows multiple users to share a single VM while still getting a full desktop experience, significantly reducing VM count and costs.Step 3: Create an Azure Virtual Desktop Host Pool
The host pool defines the collection of Azure virtual machines (session hosts) that provide desktops and applications to your users. For SMBs, we highly recommend a Pooled host pool with Breadth-first load balancing for optimal resource utilization and cost savings. We'll utilize the streamlined "Session host configuration" (currently in preview) for simplified VM lifecycle management directly within the host pool.
az desktopvirtualization hostpool create \
--name "avd-hostpool-prod" \
--resource-group "avd-rg-skycore-prod" \
--location "canadacentral" \
--host-pool-type "Pooled" \
--load-balancer-type "BreadthFirst" \
--preferred-app-group-type "Desktop" \
--managed-identity "SystemAssigned" \
--initial-session-hosts 2 \
--vm-size "Standard_D2s_v5" \
--os-disk-type "StandardSSD_LRS" \
--image-publisher "MicrosoftWindowsDesktop" \
--image-offer "Windows-11" \
--image-sku "win11-22h2-avd" \
--vnet-name "avd-vnet-skycore" \
--subnet-name "avd-subnet" \
--domain-join-user-principal-name "AVDJOURNAL@skycore.onmicrosoft.com" \
--domain-join-password "YourSecurePassword!"
--name "avd-hostpool-prod": A descriptive name for your host pool.--host-pool-type "Pooled": Recommended for SMBs for cost efficiency, allowing multiple users per VM.--load-balancer-type "BreadthFirst": Distributes new user sessions evenly across available session hosts, ensuring better performance distribution.--preferred-app-group-type "Desktop": Indicates that this host pool will primarily deliver full desktop experiences.--managed-identity "SystemAssigned": Assigns a system-managed identity to the host pool. This identity (along with appropriate RBAC roles automatically assigned during host pool creation, assuming your Azure account has permission to do so) allows AVD to manage the lifecycle of your session hosts securely, replacing the need for an Azure Desktop Service principal.--initial-session-hosts 2: Specifies to initially deploy two session host VMs. You can scale this later.--vm-size "Standard_D2s_v5": A good balance of CPU (2 vCPUs) and RAM (8 GB) for general SMB workloads, offering cost-effectiveness.--os-disk-type "StandardSSD_LRS": Standard SSDs provide a good balance of performance and cost for most SMB use cases.--image-publisher "MicrosoftWindowsDesktop" --image-offer "Windows-11" --image-sku "win11-22h2-avd": Specifies a Windows 11 Enterprise multi-session image (version 22H2) from the Azure Gallery, optimized for AVD.--vnet-name "avd-vnet-skycore" --subnet-name "avd-subnet": Connects the session hosts to the previously created virtual network and subnet.--domain-join-user-principal-name "AVDJOURNAL@skycore.onmicrosoft.com" --domain-join-password "YourSecurePassword!": Credentials for a Microsoft Entra ID user with permissions to join devices to your domain. For hybrid AD, this would be an on-premises AD user. Replace with your actual UPN and a secure password.
Portal alternative:
- Search for "Azure Virtual Desktop", then click "Host pools" under "Manage".
- Click "+ Create".
- On the "Basics" tab, select your "Subscription", "Resource group" (
avd-rg-skycore-prod), "Host pool name" (avd-hostpool-prod), "Region" (Canada Central). Choose "Pooled" for "Host pool type" and "Breadth-first" for "Load balancing algorithm". For "Maximum session limit" (per VM), use 2 or 3 for D2s_v5. - On the "Virtual Machines" tab, enable "Session host configuration (preview)". Set "Add Azure virtual machines" to "Yes". For "Instance details", specify "Number of VMs" (e.g.,
2), "VM size" (Standard_D2s_v5). Select "Image type" as "Gallery" and choose "Windows 11 Enterprise multi-session + Microsoft 365 Apps" (or your preferred image). Select your VNet and Subnet. Provide "Domain join options" and credentials. Assign a "System assigned managed identity". - Review and create.
Run this to verify:
az desktopvirtualization hostpool show --name "avd-hostpool-prod" --resource-group "avd-rg-skycore-prod" --query "{name:name, hostPoolType:hostPoolType, loadBalancerType:loadBalancerType}"
az vm list --resource-group "avd-rg-skycore-prod" --query "[].name"
Azure Virtual Desktop licensing can be complex. Ensure every user accessing AVD has a qualifying Microsoft 365 or Windows Enterprise license. Failing to do so can lead to compliance issues and unexpected costs. Consult with a licensing specialist if unsure.
Step 4: Create and Link an Azure Virtual Desktop Workspace
A workspace logically groups your host pools and application groups. Users subscribe to a workspace to see all their assigned desktops and applications. Your host pool needs to be registered with a workspace.
az desktopvirtualization workspace create \
--name "avd-workspace-skycore" \
--resource-group "avd-rg-skycore-prod" \
--location "canadacentral"
az desktopvirtualization workspace update \
--name "avd-workspace-skycore" \
--resource-group "avd-rg-skycore-prod" \
--host-pool "avd-hostpool-prod"
az desktopvirtualization workspace create: Creates the workspace itself.az desktopvirtualization workspace update --host-pool: Associates your newly created host pool with this workspace.
Portal alternative:
- In the Azure Virtual Desktop blade, click "Workspaces" under "Manage".
- Click "+ Create". Select your "Subscription", "Resource group", give it a "Name" (e.g.,
avd-workspace-skycore), and "Region" (Canada Central). - On the "Application groups" tab, select your
avd-hostpool-prod-DAG(the default desktop application group automatically created with your host pool). Review and create.
Run this to verify:
az desktopvirtualization workspace show --name "avd-workspace-skycore" --resource-group "avd-rg-skycore-prod" --query name
Step 5: Assign Users to Application Groups
To grant users access to the virtual desktops or applications, you need to assign them to an application group. When you created the host pool, a default desktop application group (-DAG suffix) was automatically created. We'll assign an Azure AD group to this default desktop application group.
# First, get the object ID of your Azure AD group (e.g., 'AVD Users Group')
az ad group show --group "AVD Users Group" --query id --output tsv
# Replace with the ID obtained above
az role assignment create \
--assignee-object-id "" \
--role "Desktop Virtualization User" \
--resource-group "avd-rg-skycore-prod" \
--scope "/subscriptions//resourceGroups/avd-rg-skycore-prod/providers/Microsoft.DesktopVirtualization/applicationGroups/avd-hostpool-prod-DAG"
az ad group show: Retrieves the object ID of your target Microsoft Entra ID security group (e.g.,AVD Users Group). Ensure this group contains all users who should access AVD.az role assignment create: Assigns theDesktop Virtualization Userrole to the specified Azure AD group for your default desktop application group (avd-hostpool-prod-DAG). This grants members of the group permission to access the published desktop.- Remember to replace
<AZURE_AD_GROUP_ID>and<YOUR_SUBSCRIPTION_ID>with your actual values.
Portal alternative:
- In the Azure Virtual Desktop blade, navigate to "Application groups" under "Manage".
- Select your default desktop application group (e.g.,
avd-hostpool-prod-DAG). - Under "Manage", click "Assignments".
- Click "+ Add" and search for your Azure AD user or group. Select it and click "Select".
Run this to verify:
az desktopvirtualization applicationgroup show --name "avd-hostpool-prod-DAG" --resource-group "avd-rg-skycore-prod" --query name
# (No direct CLI command to list user assignments easily, portal is best for verification here)
Step 6: Configure Diagnostics and Monitoring
Enabling diagnostics for your AVD components is crucial for troubleshooting user connection issues, session host performance, and general service health. We'll send logs to a Log Analytics Workspace.
# Create a Log Analytics Workspace if you don't have one
az monitor log-analytics workspace create \
--resource-group "avd-rg-skycore-prod" \
--workspace-name "avd-loganalytics-skycore" \
--location "canadacentral"
# Get the Log Analytics Workspace ID
LOG_ANALYTICS_WORKSPACE_ID=$(az monitor log-analytics workspace show \
--resource-group "avd-rg-skycore-prod" \
--workspace-name "avd-loganalytics-skycore" \
--query id --output tsv)
# Configure diagnostic settings for the Host Pool
az monitor diagnostic-settings create \
--name "avd-hostpool-diag" \
--resource-group "avd-rg-skycore-prod" \
--resource "/subscriptions//resourceGroups/avd-rg-skycore-prod/providers/Microsoft.DesktopVirtualization/hostPools/avd-hostpool-prod" \
--workspace "$LOG_ANALYTICS_WORKSPACE_ID" \
--logs '[{"categoryGroup": "allLogs", "enabled": true}]' \
--metrics '[{"category": "AllMetrics", "enabled": true}]'
# Configure diagnostic settings for the Workspace
az monitor diagnostic-settings create \
--name "avd-workspace-diag" \
--resource-group "avd-rg-skycore-prod" \
--resource "/subscriptions//resourceGroups/avd-rg-skycore-prod/providers/Microsoft.DesktopVirtualization/workspaces/avd-workspace-skycore" \
--workspace "$LOG_ANALYTICS_WORKSPACE_ID" \
--logs '[{"categoryGroup": "allLogs", "enabled": true}]' \
--metrics '[{"category": "AllMetrics", "enabled": true}]'
az monitor log-analytics workspace create: Sets up a Log Analytics Workspace to collect logs and metrics.LOG_ANALYTICS_WORKSPACE_ID=$(...): Captures the ID of your workspace for subsequent commands.az monitor diagnostic-settings create: Configures diagnostic settings for both the host pool and workspace, sending all logs and metrics to the Log Analytics Workspace.- Remember to replace
<YOUR_SUBSCRIPTION_ID>with your actual subscription ID.
Portal alternative:
- Search for "Log Analytics Workspaces" and create one if needed.
- Navigate to your "Host pool" (
avd-hostpool-prod). Under "Monitoring", click "Diagnostic settings", then "+ Add diagnostic setting". Select "Send to Log Analytics workspace", choose your workspace, and select all log categories and metrics. - Repeat for your "Workspace" (
avd-workspace-skycore).
Run this to verify:
az monitor diagnostic-settings list --resource-group "avd-rg-skycore-prod" --query "[?contains(name, 'avd')].name"
Step 7: Implement Core Security Best Practices
Security is paramount for any cloud deployment. Azure Virtual Desktop leverages Azure's robust security features. Implementing these best practices will significantly harden your environment.
# Create Network Security Group (NSG) for session hosts
az network nsg create \
--name "avd-nsg-sessionhosts" \
--resource-group "avd-rg-skycore-prod" \
--location "canadacentral"
# Associate NSG with the subnet (replace with your VNet's resource ID)
# To get VNET_ID: az network vnet show --name "avd-vnet-skycore" --resource-group "avd-rg-skycore-prod" --query id --output tsv
az network vnet subnet update \
--name "avd-subnet" \
--vnet-name "avd-vnet-skycore" \
--resource-group "avd-rg-skycore-prod" \
--network-security-group "avd-nsg-sessionhosts"
# Add an NSG rule to allow outbound internet access (for updates/browsing)
az network nsg rule create \
--name "AllowOutboundInternet" \
--nsg-name "avd-nsg-sessionhosts" \
--resource-group "avd-rg-skycore-prod" \
--priority 100 \
--source-address-prefixes "VirtualNetwork" \
--destination-address-prefixes "Internet" \
--destination-port-ranges "*" \
--direction "Outbound" \
--access "Allow" \
--protocol "*" \
--description "Allow outbound internet access for session hosts"
# AVD uses reverse connect, so no inbound ports are needed for client connections.
# However, if you need RDP for admin access from specific IPs, add a rule:
az network nsg rule create \
--name "AllowRDPFromAdminIP" \
--nsg-name "avd-nsg-sessionhosts" \
--resource-group "avd-rg-skycore-prod" \
--priority 200 \
--source-address-prefixes "YOUR_ADMIN_PUBLIC_IP_RANGE" \
--destination-address-prefixes "*" \
--destination-port-ranges "3389" \
--direction "Inbound" \
--access "Allow" \
--protocol "Tcp" \
--description "Allow RDP for administrators from specific IPs"
- Network Security Groups (NSGs): By default, AVD uses reverse connect, meaning no inbound ports need to be opened for client connectivity. However, you should still control network traffic. We create an NSG and associate it with the subnet where your session hosts reside.
- Outbound Internet Access: Session hosts typically need outbound internet access for Windows Updates, software installations, and user browsing.
- Admin Access (Optional but Recommended): For administrative tasks (e.g., direct RDP to a session host), create a highly restrictive inbound RDP rule, allowing access ONLY from your known administrative IP addresses. Replace
YOUR_ADMIN_PUBLIC_IP_RANGEwith your actual public IP address or range. - Microsoft Entra ID / MFA / Conditional Access: Ensure Multi-Factor Authentication (MFA) is enforced for all AVD users via Microsoft Entra ID. Implement Conditional Access policies to further secure access, for instance, requiring compliant devices or trusted locations. (These are configured in the Microsoft Entra admin center, not via CLI).
- Least Privilege: Follow the principle of least privilege. AVD administrators should be assigned granular RBAC roles (e.g., "Desktop Virtualization Contributor" on specific resource groups) rather than subscription-level owners.
Portal alternative:
- Search for "Network security groups" and create one.
- Navigate to your VNet (
avd-vnet-skycore), then "Subnets", and click onavd-subnet. Assign the newly created NSG. - Within the NSG, add inbound and outbound security rules as described above.
- For MFA and Conditional Access, navigate to the Microsoft Entra admin center.
Run this to verify:
az network nsg rule list --nsg-name "avd-nsg-sessionhosts" --resource-group "avd-rg-skycore-prod" --query "[].name"
Step 8: Test User Connectivity and Experience
With your Azure Virtual Desktop environment deployed and users assigned, the final step is to verify that users can successfully connect to their virtual desktops and applications. This confirms your setup is complete and functional.
Instruct your users to:
- Download the Remote Desktop Client: The recommended client is the Windows App (formerly Remote Desktop Client) for Windows, macOS, iOS, or Android. For Linux, use a compatible RDP client.
- Subscribe to the Workspace:
- Open the Windows App.
- Click "Add" and choose "Workspace".
- Enter the subscription URL:
https://rdweb.wvd.microsoft.com/api/arm/feeddiscovery - Sign in with their Azure AD credentials (the user must be part of the group assigned in Step 5).
- Launch Desktop/Application: Once subscribed, the published desktop (e.g., "SessionDesktop") will appear. Users can click on it to launch their virtual desktop.
- Web Client Alternative: Users can also access AVD via a web browser by navigating to https://client.wvd.microsoft.com/, signing in with their Azure AD credentials, and launching their resources.
Run this to verify: (User-side verification)
- Attempt to connect from a client device using the provided instructions.
- Verify that the desktop loads correctly and applications are accessible.
When to bring in a consultant
While this Azure Virtual Desktop setup guide covers the essential steps for a functional deployment, complex scenarios often benefit from expert guidance. Consider engaging SkyCore Solutions if you face:
- Hybrid Identity Challenges: Integrating AVD with intricate on-premises Active Directory environments and legacy applications.
- Advanced Networking: Designing secure network topologies with Azure Firewall, VPNs, or ExpressRoute for specific compliance needs.
- Optimized Performance: Fine-tuning VM sizing, FSLogix profile management (beyond basic setup), or custom image creation for demanding workloads.
- Comprehensive Security Hardening: Implementing advanced security controls, compliance frameworks, or integrating with existing SIEM solutions.
- Automated Scaling and Cost Management: Setting up sophisticated auto-scaling plans to dynamically adjust session host capacity based on demand and control costs.
- Application Packaging and Delivery: Deploying complex line-of-business applications or migrating existing RDS environments.
Our team of senior Azure architects specializes in tailoring cloud solutions for SMBs, ensuring your Azure Virtual Desktop deployment is not just functional, but perfectly aligned with your business goals and security posture.
Book a free consultation