This article is a 4th part of a series regarding WVD deployment.
Previous articles from the series could be found here:
- https://www.azureblog.pl/2020/09/19/windows-virtual-desktop-deployment-1-5/
- https://www.azureblog.pl/2020/10/07/windows-virtual-desktop-deployment-2-5/
- https://www.azureblog.pl/2020/10/09/windows-virtual-desktop-deployment-3-5/
Today I’d like to walk you through the custom image optimization using:
- Prerequisites
- OS Configuration
- Virtual Desktop Optimization Script
- FSLogix configuration
Prerequisites
Before we proceed please deploy 1 VM described below:
- VM1: OS: Windows 10 Enterprise multi-session, Version 2004., Disk Type: Managed
- Authentication source: Azure AD DS / Active Directory synchronized with Azure AD
OS configuration
This will be a easy configuration as we are going to
- Disable Windows updates
- Configure Time Zone redirection
- Disable Storage Sense
Of course, you can configure as much as you wish. I’m showing only the part of the configuration.
In order to do that we need log in to the VM1 and run the following code:
$VerbosePreference = "continue"
Write-Verbose "Disabling Windows updates"
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v NoAutoUpdate /t REG_DWORD /d 1 /f
Write-Verbose "Configuring Time zone redirection"
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fEnableTimeZoneRedirection /t REG_DWORD /d 1 /f
Write-Verbose "Disabling Storage Sense"
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy" /v 01 /t REG_DWORD /d 0 /f
Picture below presents the output of the code
This is all about the OS configuration part.
Virtual desktop optimization script
In this part we are going to use the script available on GitHub under:
- My repo – https://github.com/przybylskirobert/Virtual-Desktop-Optimization-Tool
- The original one – https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool
Download and run script into our VM1 machine using code below
#region Variables
$verboseSettings = $VerbosePreference
$VerbosePreference = 'Continue'
$toolsPath = "C:\Tools"
$optimalizationScriptURL = 'https://github.com/przybylskirobert/Virtual-Desktop-Optimization-Tool/archive/master.zip'
$optimalizationScriptZIP = "$toolsPath\WVDOptimalization.zip"
$OptimalizationFolderName = "$toolsPath\" + [System.IO.Path]::GetFileNameWithoutExtension("$optimalizationScriptZIP")
$toolsTest = Test-Path -Path $toolsPath
if ($toolsTest -eq $false){
Write-Verbose "Creating '$toolsPath' directory"
New-Item -ItemType Directory -Path $toolsPath | Out-Null
}
else {
Write-Verbose "Directory '$toolsPath' already exists."
}
#endregion
#region Optimalization
Write-Verbose "Downloading '$optimalizationScriptURL' into '$optimalizationScriptZIP'"
Invoke-WebRequest -Uri $optimalizationScriptURL -OutFile $optimalizationScriptZIP
New-Item -ItemType Directory -Path "$OptimalizationFolderName"
Write-Verbose "Expanding Archive '$optimalizationScriptZIP ' into '$OptimalizationFolderName'"
Expand-Archive -LiteralPath $optimalizationScriptZIP -DestinationPath $OptimalizationFolderName
Set-Location "$OptimalizationFolderName\Virtual-Desktop-Optimization-Tool-master"
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
#endregion
Image below outlines variables region output
The last step is to run the script using the following line of code.
You could notice that some parts of the code might end up with errors, you could lose your RDP connection for a couple of seconds but don’t worry it is the desired result.
.\Win10_VirtualDesktop_Optimize.ps1 -WindowsVersion 2004 -Verbose
When the script will finish you will be notified that a system reboot is required. After the reboot optimization will be finished.
FSLogix configuration
This part have some prerequisites:
- VM1 has to be domain joined
- Storage Account has to be created for Azure Files usage
- Storage Account has to be domain joined
- AZ module installed on the VM1
- Active Directory module installed on the VM1
- Domain Users SID is required for the FSLogix configuration
The first point is pretty easy so we will skip it and focus on the storage Account deployment and configuration
FSLogix overview
Before we will start the deployment of the resources let me just show you the diagrams of why we need a storage account
As you can see we are going to integrate Azure Files (storage account) with Active AD DS. This will create a computer account with the same name as your storage account.
Someone could ask: Why we are going to use Private endpoint?
The private endpoint will limit access to this Azure File share only for the specific network. It will be inaccessible from the Internet.
The diagram above describes the usage of the FSLogix with Azure Files.
All user profile related files will be stored on a dedicated VHD file placed on the Azure Files. It will allow to re-deploy session hosts without any blockers related to the user data stored on them.
Storage Account deployment
Let’s go to the Azure portal and go inside resource group rg-wvd-mgmt dedicated to WVD management resources.
Click Add on the top menu and on the next screen chose Storage Account
On the Basic screen fill the following:
- Storage Account Name: this name has to be globally unique
- Location: Same as the Resource Group
- Performance: Premium
- Account kind: FileStorage
- Replication: Locally-redundant storage (LRS)
On the Networking screen fill the following:
- Connectivity method: Private endpoint
Click Add to add new Private endpoint.
On the Create private endpoint screen fill the followings:
- Location: Same as the resource group
- Name: Private endpoint name according to your naming convention
- Storage sub-resource File
- Virtual network: Virtual network that should be used for your WVD deployment. It should also be integrated with AD / Azure AD DS
- Subnet: subnet for the private endpoint usage
- Integrate with private DNS zone: No
When the private endpoint configuration is done click Review+Create and deploy the resources.
Now we can go to the our storage account and proceed with the configuration from the Azure portal perspective.
Find our private endpoint and copy its FQDN and Private IP
Go to the storage account that we just created and click on the Access Control (IAM)
On the Access Control screen we need to add the following roles assignment:
- Storage File Data SMB Share Contributor – In my case I’m assigning it to the WVD_users group
- Storage File Data SMB Share Elevated Contributor: In my case, I’m assigning it to the domop@lab.azureblog.pl user
This is it for now. Let’s switch to the VM1 and join our storage account to the domain
Storage Account domain join
Log in to the VM1 using your account that has privileges to add objects to the domain.
Run the following code using PowerShell
$VerbosePreference = 'continue'
$ToolsPath = 'C:\Tools'
$AzFilesPath = 'https://github.com/Azure-Samples/azure-files-samples/releases/download/v0.2.2/AzFilesHybrid.zip'
$StorageAccountName = 'stfsazureblog'
$StorageAccountResourceGroupName = 'rg-wvd-mgmt'
$moduleName = [System.IO.Path]::GetFileNameWithoutExtension("$AzFilesPath")
$azFilesZip = "$ToolsPath\$($moduleName).zip"
$azFilesFolderName = "$ToolsPath\$moduleName"
$toolsTest = Test-Path -Path $ToolsPath
if ($toolsTest -eq $false) {
Write-Verbose "Creating '$ToolsPath' directory"
New-Item -ItemType Directory -Path $ToolsPath | Out-Null
}else {
Write-Verbose "Directory '$ToolsPath' already exists."
}
Write-Verbose "Downloading '$AzFilesPath' into '$azFilesZip'"
Invoke-WebRequest -Uri $AzFilesPath -OutFile $azFilesZip
New-Item -ItemType Directory -Path "$azFilesFolderName"
Write-Verbose "Expanding Archive '$azFilesZip ' into '$azFilesFolderName'"
Expand-Archive -LiteralPath $azFilesZip -DestinationPath $azFilesFolderName
$IP = Read-Host "Please provide storage account private endpoint IP"
$storageAccountName = Read-Host "Please provide storage account name"
Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "$IP``$($storageAccountName).file.core.windows.net" -Force
notepad C:\Windows\System32\drivers\etc\hosts
Connect-AzAccount
Set-Location $azFilesFolderName
.\CopyToPSPath.ps1
$moduleTest = Get-Module -Name 'AzFilesHybrid'
if ($moduleTest -eq $null) {
Write-Verbose "Importing module 'AzFilesHybrid'"
Import-Module -Name AzFilesHybrid
}
Images below depicted configuration progress.
You will be asked to log on to the Azure
After the module installation, you will need to close the PowerShell session.
Run the following code in the new PowerShell window
$StorageAccountName = 'stfsazureblog'
$StorageAccountResourceGroupName = 'rg-wvd-mgmt'
Import-Module -Name AZfilesHybrid
Connect-AzAccount
$VerbosePreference = "continue"
Write-Verbose "Joining storage account '$StorageAccountName' into the domain."
Join-AzStorageaccountForAuth -ResourceGroupName $StorageAccountResourceGroupName -Name $StorageAccountName -DomainAccountType "ComputerAccount"
Write-Verbose "Remember to assign NTFS permissions on a network share."
Write-Verbose "User Account Folder Permissions"
Write-Verbose "Users This Folder Only Modify"
Write-Verbose "Creator / Owner Subfolders and Files Only Modify"
Write-Verbose "Administrator (optional) This Folder, Subfolders, and Files Full Control."
As we are using Azure AD DS we need to do one more thing from Azure Portal.
Go to the storage account configuration and Disable
Active Directory Domain Services (AD DS) integration. Save your change and then switch Azure Active Directory Domain Services (Azure AD DS) to Enabled again save your changes.
From this moment our Azure Files share is available for users authenticated to the Azure AD DS
Azure File share configuration
Let’s configure NTFS permissions on Azure Files Share.
In order to do that we need to configure share under Azure Files.
Go to the Azure Portal / Storage Account configured for Azure Files and create a new share called fslogixprofiles with 1024GiB capacity
From the VM1 access the following network share:
\\StorageAccountName.file.core.windows.net\fslogixprofiles\
where StorageAccountName is stfsazureblog and the full path looks like
\\stfsazureblog.file.core.windows.net\fslogixprofiles\
Open share Properties and go to the Security Tab
From the advanced settings assign the following permissions:
User Account | Folder | Permissions |
Users | This Folder Only | Modify |
Creator / Owner | Subfolders and Files Only | Modify |
Administrator | This Folder, Subfolders, and Files | Full Control |
Image below describes the settings configured on the LAB environment
Domain Users SID
To get the Domain Users group SID run the following command.
Remember that SID value will be different for each Active Directory deployment.
Get-ADGroup -Identity "Domain Users" | ft Name,SID
In our Domain Users SID is S-1-5-21-1581098281-3520177802-4203237917-513
FSLogix Installation
Now it is the time to install FSLogix.
As always we are going to do that using PowerShell code below:
$VerbosePreference = 'Continue'
$toolsPath = "C:\Tools"
$fsLogixURL = "https://aka.ms/fslogix_download"
$fslogixZip = "$toolsPath\FSLogix.zip"
$fslogixFolderName = "$toolsPath\" + [System.IO.Path]::GetFileNameWithoutExtension("$fslogixZip")
$toolsTest = Test-Path -Path $toolsPath
if ($toolsTest -eq $false){
Write-Verbose "Creating '$toolsPath' directory"
New-Item -ItemType Directory -Path $toolsPath | Out-Null
}
else {
Write-Verbose "Directory '$toolsPath' already exists."
}
Write-Verbose "Downloading '$fsLogixURL' into '$fslogixZip'"
Invoke-WebRequest -Uri $fsLogixURL -OutFile $fslogixZip
New-Item -ItemType Directory -Path "$fslogixFolderName"
Write-Verbose "Expanding Archive '$fslogixZip ' into '$fslogixFolderName'"
Expand-Archive -LiteralPath $fslogixZip -DestinationPath $fslogixFolderName
Set-Location "$fslogixFolderName\x64\Release"
Write-Verbose "Installing FSLogix software"
.\FSLogixAppsSetup.exe /quiet /norestart /install
After couple minutes we should see the output similar as below
FSLogix Configuration
This is the last step regarding FSLogix configuration.
We are going to configure registry settings that will setup the VM1 for the FSLogix usage.
More information’s regarding FSLogix configuration could be found here:
https://docs.microsoft.com/en-us/fslogix/profile-container-configuration-reference
$VerbosePreference = 'Continue'
$storageAccountName = Read-Host "Please provide storage account name for FSLogix usage"
$regPath = "HKLM:\SOFTWARE\FSLogix\Profiles"
New-Item -Path $regPath -Force | Out-Null
New-ItemProperty -Path $regPath -name "Enabled" -PropertyType "DWord" -Value "1" -Force | Out-Null
New-ItemProperty -Path $regPath -name "VHDLocations" -PropertyType "String" -Value "\\$($storageAccountName).file.core.windows.net\fslogixprofiles" -Force | Out-Null
New-ItemProperty -Path $regPath -name "VolumeType" -PropertyType "String" -Value "VHDX" -Force | Out-Null
New-ItemProperty -Path $regPath -name "SizeInMBs" -PropertyType "DWord" -Value "2000" -Force | Out-Null
New-ItemProperty -Path $regPath -name "IsDynamic" -PropertyType "DWord" -Value "00000001" -Force | Out-Null
New-ItemProperty -Path $regPath -name "LockedRetryCount" -PropertyType "DWord" -Value "00000003" -Force | Out-Null
New-ItemProperty -Path $regPath -name "LockedRetryInterval" -PropertyType "DWord" -Value "00000005" -Force | Out-Null
New-ItemProperty -Path $regPath -name "FlipFlopProfileDirectoryName" -PropertyType "DWord" -Value "00000001" -Force | Out-Null
New-ItemProperty -Path $regPath -name "DeleteLocalProfileWhenVHDShouldApply" -PropertyType "DWord" -Value "00000001" -Force | Out-Null
New-ItemProperty -Path $regPath -name "PreventLoginWithTempProfile" -PropertyType "DWord" -Value "00000000" -Force | Out-Null
New-ItemProperty -Path $regPath -name "PreventLoginWithFailure" -PropertyType "DWord" -Value "00000001" -Force | Out-Null
$sid_LocalAdministrators = 'S-1-5-32-544'
$sid_DomainUsers = (Get-ADGroup -identity 'Domain Users' -Properties *).SID.value
Remove-LocalGroupMember -Group 'FSLogix Profile Include List' -Member 'Everyone' | Out-Null
Add-LocalGroupMember -Group 'FSLogix Profile Include List' -Member $sid_DomainUsers | Out-Null
Add-LocalGroupMember -Group 'FSLogix Profile Exclude List' -Member $sid_LocalAdministrators | Out-Null
So FSLogix finally configured. Now we can logo off from the VM1 and logon one more time to see if the FSLogix Profile works properly
Next steps
Finally we have managed to customize our golden image, optimize it using dedicated script and setup FSLogix.
With all those settings we can create image from VM1 and use it in our environment.
Comments are closed.