Skip to main content

· 17 min read

Previously known as Windows Virtual Desktop, Azure Virtual Desktop is the successor of Microsoft Remote Desktop; although compatible with Server OS (Operating System), it is the first to support Windows 10_(and soon Windows 11)_ multisession, reducing application compatibility issues and giving consistent user experience.

In this guide, I will run you through creating Azure Virtual Desktop from scratch, along with some prerequisites that will help you manage AVD after you create it.

Before I begin, I recommend reading the Azure Virtual Desktop Azure product page "here" to understand the pricing model, features and additional resources that could help you in your journey.

When selecting a region for your Session Hosts (Virtual Machines), I recommend you have a look at the: Azure Virtual Desktop Experience Estimator to help validate the proper region for your Session Hosts and the round trip time (I am in New Zealand, so my recommended region is: Australia East, which is what I will be using for this guide).

If you don't already have a Microsoft Azure subscription, you can sign up for a Free subscription "here".

Assuming you already have an Azure subscription and the appropriate access to create resources in that subscription, gets begin!

Create Microsoft Entra ID Domain Services

  1. Log in to the Azure Portal
  2. Click on Create a resource
  3. Search for: Azure AD Domain Services. You can change the Publisher Type to Microsoft, so it doesn't display any other marketplace offerings. Azure AD Domain - Marketplace Azure AD Domain - Marketplace
  4. Click Create
  5. If you already have a Resource Group, select it - in this Demo, we are going to create one: aad_prod
  6. Type in the DNS domain name - this is the FQDN of your domain; in my demo, I will choose internal.luke.geek.nz.
  7. Because I am in New Zealand, the closest region to me is Australia East, so that’s the region I will select. Make sure you select the appropriate region for where your Azure Virtual Desktop workloads are.
  8. Select the SKU and Resource Type; you can see the Pricing Calculator and the "Help Me choose.." links to verify your SKU and Forest type (however, in most cases, such as Azure Virtual Desktop, your Forest Type will be 'User'). Azure AD Domain Services - Basic Config
  9. Click Next
  10. We will set up the Networking; if you have an already existing Virtual Network, select it. Azure AD Domain Services uses a dedicated subnet within a virtual network to hold all of its resources. If using an existing network, ensure that the network configuration does not block the ports required for Azure AD Domain Services to run. Learn more
  11. I will let it create a Virtual Network and its Subnet (/24); click Next. Azure AD Domain Services - Networking Config
  12. Azure AD Domain Services will create a new Azure AD Group called: AAD DC Administrators - this group will be used for Administrator level permissions on the Azure AD Domain Services domain (it automatically adds the account you are using to create Azure AD Domain Services into this group).
  13. You can configure Membership of this group now and configure who gets alerted if there are issues with Azure AD Domain Services.
  14. When you are ready, select Next. Azure AD Domain Services - Administration Config
  15. Depending on the amount of Microsoft Entra ID users you have in your organisation, and whether they will need Azure AD Domain Services, you can choose to synchronise ALL Azure AD Groups and Users, or specific groups of users (this can be changed later), because my Azure AD Organisation is fairly low, I am going to Sync everything, click Next.
  16. One thing to note here is the recommendation on the number of Objects (Users, Groups) that will get synced to Azure AD Domain Services; for the Standard SKU, the suggested Object Count is 0 to 25,000 - for the Enterprise SKU, it is 25,000 to 100,000. So although there is no hard limit, it might be worth upgrading the SKU you are running for the additional backups and authentication if fit in the Enterprise space. Azure AD Domain Services - Syncronisation Config
  17. We can now configure the Security Settings, the only setting I am going to change here is TLS 1.2 Only Mode to Enable Azure AD Domain Services - Security Config
  18. Enter any applicable Tags and click Review & Create to validate your configuration.
  19. Review your configuration, and if you are happy with it: Select Create.
  20. Confirm that you are happy with the following and click Ok Azure AD Domain Services Note: Azure AD Domain Services can take up to an hour to provision.
  21. Once your Azure AD Domain Services has been configured, we must make some final configuration changes to point the Virtual Network DNS to use the Azure AD Domain Services. So first, open your newly created Azure AD Domain Services.
  22. Click on Overview and: Configuration issues for your managed domain were detected. Run configuration Diagnostics Azure AD Domain Services
  23. Click on Run
  24. It should find a DNS record issue; click Fix to set the DNS settings of the Virtual Network to use the Azure AD Domain Services. Please be careful here, especially if you have already existing DNS settings; you might have to add it manually.

Create a Utility server to help Administer Azure Virtual Desktop

We need to create a Virtual Machine to help manage the AAD Domain and deploy Group Policies to help manage and configure the Azure Virtual Desktop farm.

  1. Log in to the Azure Portal
  2. Click on Create a resource.
  3. Search for: Windows Server 2019 Datacenter and select Create
  4. If you already have a Resource Group, select it - in this Demo, we are going to create one: aad_infra
  5. Specify a name for the Virtual Machine (I am going to use: UTILITY-P01)
  6. Select a Region (use the same Region as the Azure AD Domain Services and Azure Virtual Desktop resources)
  7. For the Image, you can select either Windows Server 2019 Datacenter -Gen 1 or Gen 2; in my case, I am going with Gen2 (although it doesn't matter).
  8. I am a firm believer in selecting the smallest size possible for the size, then scaling up when/where needed; I am going to go with a Standard_B2ms. Azure - Create VM
  9. Now we need to enter in the Administrator (local account) Username and Password.
  10. Select 'None' for Public inbound ports
  11. If you have existing Windows Server licenses, you can select Hybrid Use Benefit; if not, select Next: Disks. Azure - Create VM
  12. For the disks, I only need the OS disk, so I don't need to add a Data Disk (although you could use this to store your Application install files etc.); however, to reduce cost, I am going to change the Disk type to Standard SSD (locally-redundant storage) and select Next: Networking. Azure - Create VM
  13. For the Virtual Network, make sure you select the same Virtual Network that the Azure AD Domain Services has been installed to; I will select the: aadds-subnet created earlier for my Utility server.
  14. Set 'None' for the Public IP and select Next: Management Azure - Create VM
  15. Feel free to leave this all as Default
  16. Just be wary of the Auto-shutdown settings, which will automatically shut down the VM daily (I will keep mine selected as this is just a demo, and I only need the UTILITY server for initial configuration, it doesn't need to be running 24.7).
  17. If you have a Recovery Services Vault, now is a good time to add the Utility server to Backups, so you don't forget it later, select Review & Create
  18. Verify the configuration is correct and select Create

Create Azure Bastion to connect to the Utility server

Once the VM has been created, we now need to connect to it securely, so we will create a Bastion instance, which will allow us to connect to it without publishing the RDP (Remote Desktop Protocol) over the internet.

  1. Log in to the Azure Portal
  2. Click on Create a resource
  3. Search for: Bastion Azure - Bastion
  4. Click Create
  5. This is a Networking resource to place it in the same Resource Group as my Virtual Network.
  6. Please type in a Name for the Bastion instance; I will call mine: Bastion
  7. Select the Region that matches the Virtual Network region
  8. Select the Virtual Network
  9. It now warns you about creating an: AzureBastionSubnet with a prefix of at least /27, so we need to create one; click on Manage Subnet Configuration.
  10. Click + Subnet
  11. For the Name type in: AzureBastionSubnet
  12. For the Subnet address range: 10.0.1.0/27 If you get an error that indicates the address is overlapping with the aadds-subnet, it may be because the Address space is only a /24; click Cancel and click on Address Space in the Virtual Network and change the /24 to/16 to increase the address range.
  13. Click Save to create the subnet Azure - Bastion
  14. Up the Top, click Create a Bastion. To go back to the Bastion setup, your Subnet should be selected automatically.
  15. You do need a Public IP for Bastion, so confirm the name is appropriate, then click Review + Create Azure - Bastion
  16. Click on Create to create your Bastion instance!

Note: Bastion may take 10-20 minutes to provision.

Configure the Utility server

Now that we have a Bastion instance, it is time to connect and configure the Utility server and create a new Azure AD user for Azure Virtual Desktop configuration.

  1. First thing I am going to create a separate Azure AD account to manage the Utility server and join the Azure Virtual Desktop session hosts to the domain; this is to separate my own account. Azure AD Domain Services relies on password hash. So you won't be able to log in using Azure AD Domain Services unless you and the people using it have reset their passwords AFTER Azure AD Domain Services has been created.

  2. Navigate to the Azure Portal and open Microsoft Entra ID

  3. Click on Users

  4. Click on + New User

  5. Type in the username of a user, I am going to use: 'avdjoin'

  6. Type in an easily identifiable name

  7. Generate or put in a secure password

  8. Add to the AAD DC Administrators group

  9. Click Ok to create the user Azure AD - Users

  10. Once the account has been created, make sure to login with it to the Azure Portal or Office portal to force a final password reset, or you won't be able to use it in the next steps as it will be waiting for a password reset.

  11. Once that account has been created, it's time to join your utility server to the Microsoft Entra ID Domain, navigate to your Utility server and click Connect.

  12. Select Bastion

  13. Select Use Bastion

  14. Type in the username and password of the LOCAL account created when the Virtual Machine was created and click Connect Note: If you are running a popup blocker, you need to allow it to open, as Bastion opens up the connection in a new window. Azure Bastion

  15. You should now be logged in to the server successfully.

  16. Now it's time to join the server to the domain (make sure that DNS is configured for AD Domain Services on the Virtual Network, see the last step in the AD Domain Services section, or you won't be able to domain join anything).

  17. In Server Management, click on Local Server

  18. Select WORKGROUP

  19. Click Change…

  20. Select Domain

  21. Please type in the DNS name of your domain; in my demo, it is: luke.geek.nz

  22. Type in the username and password of the account we created earlier and clicked Ok Azure - Domain Join

  23. Once you see, Welcome to the domain, click Ok a few times to restart the server.

  24. Once the server has been restarted, you can now close your bastion window and reconnect using your Azure AD credentials (in my case, avdjoin), a member of the ADDC Administrators group. Azure - Connect to Bastion

  25. You have now successfully connected using an Azure AD account to the AD Services domain.

  26. Now it's time to install some base Active Directory tools

  27. Open Windows PowerShell as Administrator

  28. Type in the following PowerShell commands:

    Add-WindowsFeature RSAT-Role-Tools

    Install-WindowsFeature –Name GPMC

Note: You can use the little arrows on the left-hand side of your Remote Desktop window to copy and paste text to and from your Bastion connection.

  1. This will now install the base Active Directory remote management tools, including Group Policy Management, so you can now create and manage the Group Policy objects for your Azure Virtual Desktop hosts. Server Tools
  2. We will now set up some base configurations to create a custom OU for the Azure Virtual Desktops hosts to go into:
  • Open Active Directory Users & Computers
  • Expand out the Domain and right-click (at the Top Level)
  • Select New, Organisational Unit

Server Tools

  • Type in: AVD
  • In the AVD OU, create a new OU called: Hosts
  • Now that we have an OU for the hosts, we will need to tell Azure what OU the hosts go into, so while we have Active Directory Users and Computers open, click on View.
  • Select Advanced Features
  • Right-click the Hosts OU
  • Select Properties
  • Click on Attribute Editor
  • Find the distinguishedName attribute

Server Tools

  • Open and Copy the Value for future (in my case: OU=Hosts,OU=AVD,DC=luke,DC=geek,DC=nz) for future reference.
  • Now that we have the AVD Hosts OU, you can also open Group Policy Management and create your Computer policies.

Deploy Azure Virtual Desktop

Now we are ready to deploy Azure Virtual Desktop finally!

  1. Log in to the Azure Portal
  2. Click on Create a resource
  3. Find and select Host pool Azure Virtual Desktop - Host Pool
  4. Click Create
  5. Please create a new Resource Group to help resources separately, and I am going to name mine: avd_prod
  6. Type in a Host Pool Name, I will call mine: avd-pooled
  7. Please select the location of the Metadata (this is NOT the location of your session hosts, it’s the gateway, select the Region closet to you as possible)
  8. For Host Pool Type, if you want everyone to have a Virtual Machine each, you can select Personal; however, I want people to be shared across my servers, so I will select Pooled.
  9. For the Load balancing algorithm, we can choose to spread people over available hosts or fill up one host before moving connections to the next; we are going with Breadth-first.
  10. Click Next: Virtual Machines Azure Virtual Desktop - Host Pool
  11. Now we can add your Session hosts to the Pool.
  12. By default, it has defaulted the Resource Group to the same Resource Group as the Host pool; however, you can separate them.
  13. Please select a Name prefix for your session hosts, and it must be unique. Azure will automatically add a number to it as you build out more sessions hosts. I will put avdhost.
  14. As I am based in New Zealand, I will be using the Australia East region.
  15. We are going to use a Gallery Image of Windows 10 Enterprise multi-session, Version 20H2 + M365 Apps (select the newest image at the time of your deployment)
  16. Select your Virtual machine size
  17. Select the number of Virtual Machines you need
  18. Select the OS disk type Azure Virtual Desktop - Host Pool
  19. Select your Virtual Machine and subnet
  20. Select Yes to specify your domain or unit
  21. Type in your AD Domain Services domain name
  22. If you don't specify an OU, it will create it in the: AADDC Computers OU. I had previously created a separate OU for my hosts so that I will enter the OU information.
  23. For the Domain Administrator account, I will use the AVDJoin account I created earlier.
  24. When the Virtual Machines get created, a local Administrator account will be created for each machine, and you can specify the username and password of what you want this account to be. Azure Virtual Desktop - Host Pool
  25. Click Next: WorkSpace
  26. Select Yes to Register Desktop App Group
  27. We haven’t created an Azure Virtual Desktop Workspace yet, so select Create New.
  28. Create a name for your Workspace; my example is: avd_workspace
  29. Click Ok Azure Virtual Desktop - Workspace
  30. Click on Review + Create
  31. Confirm everything looks ok and click Create Note: This may take 10-20 minutes to create your Azure Virtual Desktop resources:
  • Host Pool
  • Workspace
  • Session hosts
  1. Once the resources have been created, you should now have an Application group for the Session Desktop.
  2. Open the Application Group and click Applications; you should confirm the SessionDesktop application is listed. Azure Virtual Desktop - Application Group
  3. Click on the SessionDesktop to change the Display name (this is the resource people will see when they go to your Azure Virtual Desktop), and I changed mine to AVD Desktop. Azure Virtual Desktop - Application Group
  4. Click on Assignments
  5. These are the Users & Groups that are allowed to access your Azure Virtual Desktop.
  6. My recommendation would be to add a Group that contains your users, but in my demo, I will add in my: 'avdjoin' account. Azure Virtual Desktop - Application Group
  7. Using an assigned account, you can now navigate to**:** https://rdweb.wvd.microsoft.com/arm/webclient/index.html Azure Virtual Desktop - RD Web
  8. You can now launch your Desktop.
  9. Congratulations, you have now created and connected to Azure Virtual Desktop! Azure Virtual Desktop

Additional Configuration

  • You can Navigate to your Host Pool; under Settings, you can restrict or allow RDP settings, Device redirections and configure Display sessions.
  • Configure Start VM On Connect to help reduce your spend.
  • If you click on Session hosts, you can add additional hosts to your pool or Drain them to prevent logins.
  • If you click Application Groups, you can add RemoteApp groups to allow users to connect directly to an Application versus a Full Desktop.
  • Configure FSLogix profiles for user persistance.
  • Set Disconnected Session Time limits in Group Policy, to automatically log off Disconnected sessions after 'x' period of time.

· One min read

Did you know, that if you update PowerShell modules, the old versions can sometimes get left behind?

This little snippet with remove any old PowerShell modules (that are not the latest version), which are installed.

#requires -Version 2.0 -Modules PowerShellGet
function Remove-OldModules
{
<#
<#
authors: [Luke] Murray (Luke.Geek.NZ)
Version: 0.1
Purpose: Basic function to remove old PowerShell modules which are installed
#>

#>
$Latest = Get-InstalledModule
foreach ($module in $Latest) {

Write-Verbose -Message "Uninstalling old versions of $($module.Name) [latest is $( $module.Version)]" -Verbose
Get-InstalledModule -Name $module.Name -AllVersions | Where-Object {$_.Version -ne $module.Version} | Uninstall-Module -Verbose
}
}

Remove-OldModules

· 2 min read

Have you ever wanted to add a Log Analytics workspace to multiple Microsoft Monitoring Agent (MMA)'s before?

Maybe you are setting up Windows Defender or wanting to redirect to collect event or performance logs.

This little quick script will help get you started on automating adding a Log Analytics workspace to the MMA agent, even through a proxy.

Note: It is recommended to have the latest MMA Agent installed, this is not compatible with SCOM 2012 R2 agents, but the latest agent is supported by SCOM.

Add_LogAnalyticsWorkspace.ps1

<#

Author: Luke Murray (Luke.Geek.NZ)
Version: 0.1
Version History:

Purpose: Add an MMA agent to a Log Analytics workspace using a proxy with no user authentication.
Notes:
Find more options about the MMA Agent Object:
#$healthServiceSettings = New-Object -ComObject 'AgentConfigManager.MgmtSvcCfg'
#$proxyMethod = $healthServiceSettings | Get-Member -Name 'SetProxyInfo'

If script is being published by Configuration as a package, create a Command Line installer:
"%Windir%\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -Command .\Add_LogAnalyticsWorkspace.ps1

If the proxy requires authentication, then the following null entries need to be replaced with user,password: $mma.SetProxyInfo("$proxy","$null","$null"). If you aren't using a proxy then you can remove the entire mma.SetProxyInfo line.

Location: https://github.com/lukemurraynz/PowerOfTheShell/blob/master/OperationsMgr/Add_LogAnalyticsWorkspace.ps1
#>

$workspaceId = "INSERTLOGANALYTICSWORKSPACEIDHERE"
$workspaceKey = "INSERTLOGANALYTICSWORKSPACEKEY"
$proxy = 'ProxyIP:PORT'
$mma = New-Object -ComObject 'AgentConfigManager.MgmtSvcCfg'
$mma.AddCloudWorkspace($workspaceId, $workspaceKey)
$mma.SetProxyInfo("$proxy","$null","$null")
$mma.ReloadConfiguration()

· 3 min read

By default, Azure Web Apps are unloaded if they are idle for a set period of time (20 minutes). This way, the system can conserve resources.

The downside is that the response to the first request after the web app is unloaded is longer, as the Web App has to load into memory and present itself, which could lead to a bad user experience.

To ensure that the Azure App Service Web App is running and always available to respond to incoming HTTP(S) requests, can be set the "Always On" configuration feature to "On".

Overview

By setting the "Always On" feature of the App Service Web App to “On”, will ensure that Azure will always keep an instance of the Web App running at all times. This way when a user/client hits the Azure Front Door endpoint, the back-end Web App will always be ready to respond to that request without timing out. This will ensure the application is always available even during times of low usage or inactivity. Azure will continuously ping the website to keep the website alive.

Enabling "Always On" keeps your Apps always loaded, even when there is no traffic. It’s required for example when using continuous Web Jobs or for Web Jobs that are triggered using a CRON expression, this feature is similar to the Internet Information Services (IIS) idle time-out property.

Disabling "Always On" makes your Apps unloaded if they are idle for a set period of time. This way, the system can conserve resources. This is the reason “Always On” is set as disabled by default.

You need a minimum of Basic and Standard App Service Tiers to enable "Always On"

Having "Always On" off or on does not affect your billing or pricing, the Azure App Service billing is done at the App Service Plan level, which is charged per hour that the App Service Plan exists and is running, this is charged whether you have a WebApp or its set to "Always On" or not.

Configure Always On

Note: Any changes to applications settings and connection strings could restart your application, so make sure that you schedule this during a period you can have an intermittent outage.

  1. Log in to the Azure Portal
  2. Find your App Service and open it
  3. In the left hand Blade, under Configuration, select General Settings App Service - General Settings
  4. Navigate down to Platform Settings and click 'On' to Always On App Service - Always On
  5. Click Save

Configure Always On through Azure Policy

The Azure policy below, contains a set of 3 policies which used in combination should ensure that your web app is always on. Since the alwaysOn property is optional in the ARM deployment, a combination of 3 policies are required to ensure true compliance in the environment.

References

For more information about the "Always On" feature please see the documentation below:

· 2 min read

By default, the timezone in Microsoft Azure defaults to UTC (Universal Coordinated Time) as a standard, as a universal and consistent timezone, this makes sense - however when troubleshooting issues or attempting to schedule jobs, having the time in UTC may add additional confusion. An Azure WebApp is no exception to UTC as a standard, however, this can be changed.

As I am in 'New Zealand', I will be setting my WebApp (which is hosted in Australia East) to NZ time from UTC.

I will be using a Windows-based App Service, for this article.

Find the Timezone

The Azure App Service uses the same naming standard as Windows.

  1. To find the correct name, run the following PowerShell snippet on a Windows PC:

    Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones' | Select-Object PSChildName

Windows Terminal - Timezone

This will list all the compatible Timezone names, because I am in New Zealand, I now know that: 'New Zealand Standard Time' is the correct syntax.

For future reference, I have exported the list of compatible timezones into a CSV file below:

Set the Timezone

Making a change to the Application Settings, which includes setting the Timezone will restart the WebApp app pool, so make sure this is scheduled at a time it is acceptable for an intermittent outage.

  1. Log in to the Azure Portal
  2. Find your Azure WebApp and open it up
  3. On the left-hand side Blade, underneath Settings, click on Configuration
  4. Click on + New Application Setting
  5. Type in the following Key/Value pair: WEBSITE_TIME_ZONE | New Zealand Standard Time
  6. Click Ok
  7. Click Save to confirm and save the change.

Azure WebApp - Timezone

Test the Timezone

  1. Log in to the Azure Portal
  2. Find your Azure WebApp and open it up
  3. On the left-hand side Blade, underneath Development Tools, click on Console
  4. Type the following into the console:
  • Time
  • Date

These commands can help you confirm, that the Date and Time now your Timezone, the Azure WebApp logs etc will now be updated to use your timezone.

Azure App Service - Console