Project automate CVAD - Part one

Project automate CVAD - Part one

This post is the first in a series that guides you through automating the installation of Citrix Virtual Apps and Desktops (CVAD) using PowerShell scripts. We will cover prerequisites, configuration, and step-by-step instructions to streamline the setup process, saving you time and effort.

Every Citrix consultant I’ve worked with, talked to, danced with(maybe not), has always(maybe not always, but close to) wanted a automated installation of a Citrix backend. The amount of time spent, watching spinning wheels of doom, spinning and spinning. NO MORE, I say!
So in a very Hashicorpified world, where everyone talks about Terraform this, Terraform that. These scripts have been written in Powershell. Now is the time to watch a blue background and a bunch of letters!
Oh and yes, documentation of each scripts … CoPilot

Without further ado. Let’s dive into it.

Prerequisites for all installations in this series

  • All scripts are written for Citrix CVAD LTSR 2402 and Microsoft Windows Server 2022.
  • The user used for script execution, needs temporary sysadmin on SQL server
  • The user used for script execution, needs local administrator on every server
  • All servers needs to have Windows Server 2022 installed, domain joined and updated with latest Windows Updates
  • Create a share to host all scriptfiles
  • Execution command: Powershell.exe -executionpolicy Bypass -File .\Component\xxx.ps1 -force
  • Restart all servers

Prerequisites for this post

├── XenDesktop
│   ├── AddadminToCVADsite.ps1
│   ├── ConfigureDirector.ps1
│   ├── ConfigureXenDesktop.ps1
│   ├── InstallDDC01.ps1
│   ├── InstallDDC02.ps1
│   ├── InstallDirector.ps1
│   ├── InstallLicenseServer.ps1
│   └── JoinDDC02toSite.ps1
└── ConfigurationVariable.json

Editing ConfigurationVariable.json

The json file holds all the variables used across the different scripts. It’s possible to state almost everything in a json and import to different files.
In this case, we are importing variables to unattended installation, site configuration and so on.
It’s a simple cmdlet to import the json, which is used in every script:

$ConVarJson = Get-Content -Raw .\ConfigurationVariables.json | ConvertFrom-Json

Line 3 is the name of the installer, we are going to use across all installations Line 16 - 25 is static, and doesn’t need to edited, since it’s the default for installing the different components.
Line 28 and 29 needs to edited, to fit your setup.
JSON interprets backslashes as escape characters. So for a UNC path to work, four backslashes are needed, with two backslashes to seperate each folder.
So edit line 30, to fit your setup.
It’s the same with line 38. DomainName and serviceaccount, needs to be seperated by two backslashes.
Since this is provided As-Is and a very basic setup, line 39 will be written in cleartext. So remember to remove it afterwards.

Different site admins have been preconfigured, you just need to those groups to line 48 - 51.

{
    "AppInstallers": {
        "packagenameXenDesktop": "XenDesktopServerSetup"
    },
    "UnattendedArguments": {
        "unattendedargsDirector": "/components DESKTOPDIRECTOR /passive /noreboot /configure_firewall",
        "unattendedargsLicenseServer": "/xenapp /components LICENSESERVER /passive /noreboot /nosql /configure_firewall",
        "unattendedargsConStudio": "/xenapp /components CONTROLLER,DESKTOPSTUDIO /passive /disableexperiencemetrics /noreboot /nosql /configure_firewall",
        "unattendedargsConStudioLicDir": "/xenapp /components CONTROLLER,DESKTOPSTUDIO,LICENSESERVER,DESKTOPDIRECTOR /passive /noreboot /nosql /configure_firewall"
    },
    "Common": {
        "DomainName": "domain.local",
        "DomainDN": "DOMAIN",
        "InstallShare": "\\\\FQDN\\TO\\INSTALLSHARE",
        "DeliveryControllers": ["DDC#1","DDC#2"]
    },
    "XenDesktop": {
        "DatabaseServer": "FQDN_of_SQL_Server",
        "DatabaseName_Site": "CitrixSite",
        "DatabaseName_Logging": "CitrixLogging",
        "DatabaseName_Monitor": "CitrixMonitor",
        "DatabaseUser": "domain.local\\serviceaccount",
        "DatabasePassword": "ServiceaccountPassword",
        "XDSite": "CitrixSiteName",
        "LicenseServer": "CitrixLicenseServer",
        "LicenseServer_LicensingModel": "LicenseModel e.g. UserDevice",
        "LicenseServer_ProductCode": "License Product Code e.g. XDT",
        "LicenseServer_ProductEdition": "License Edition e.g. PLT",
        "LicenseServer_Port": "LicenseServerPort e.g. 27000",
        "LicenseServer_ProductVersion": "License Product Version e.g. 7.41 for XenDesktop 2402",
        "LicenseServer_AddressType": "LicenseServerAddressType e.g. WSL",
        "SiteAdminFullAdminGroup": "domain.local\\FullAdminGroup",
        "SiteAdminReadOnly": "domain.local\\ReadOnlyAdminGroup",
        "SiteAdminHelpDesk": "domain.local\\HelpDeskAdminGroup",
        "SiteAdminDeliveryGroup": "domain.local\\DeliveryGroupAdminGroup",
        "SiteScope": "All",
        "SiteRoleFullAdmin": "Full Administrator",
        "SiteRoleReadOnlyAdmin": "Read Only Administrator",
        "SiteRoleHelpDeskAdmin": "Help Desk Administrator",
        "SiteRoleDeliveryGroupAdmin": "Delivery Group Administrator",
        "SiteControllerAddress": "FQDN of Controller #1"
    }
}

With all the different variables set. Time for Powershell script execution.
And to quote Wolverine “LETS FUCKING GO!!”

Component installations

After each component installation, a Restart-Computer is forced.

License Server

Login to the server, which will be license server.
Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\InstallLicenseServer.ps1

Logon the server again and import a license file.

Delivery Controllers

Delivery Controller #1

Logon to the server, which will be delivery controller number one

Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\InstallDDC01.ps1

Delivery Controller #2, if applicable

Login to the server, which will be delivery controller number two

Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\InstallDDC02.ps1

Director, if appliable

Login to the server, which will used for Director

Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\InstallDirector.ps1

Single server installation

If all components is to be installed on a single server. The following needs configured:

Edit line 35 in .\XenDesktop\InstallDDC01.ps1
From:

$UnattendedArgs = $ConVarJson.UnattendedArguments.unattendedargsConStudio

To:

$UnattendedArgs = $ConVarJson.UnattendedArguments.unattendedargsConStudioLicDir

That’s line 19 in ConfigurationVariable.json
Login to the server Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\InstallDDC01.ps1

DB creation, site config

Now is the time to create a new Citrix site
Login to Delivery Controller #1
Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\ConfigureXenDesktop.ps1
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\AddadminToCVADSite.ps1

This creates three DBs on SQL. Site, Monitoring and Logging.
A site is created, with the license server from ConfigurationVariable.json. TrustXML is set to true.
An AD group is added and set to Full Administrator on all scopes.
If multiple admins needs to be configured. Add lines to AddadminToCVADSite.ps1, below line 39 e.g. if needing a Read Only admin:

$siteadminReadOnly = $ConVarJson.XenDesktop.SiteAdmin_ReadOnly
$siteroleReadOnly = $ConVarJson.XenDesktop.SiteRoleReadOnlyAdmin

Add below line 47:

New-AdminAdministrator -AdminAddress $env:COMPUTERNAME -Name "$siteadminReadOnly"
Add-AdminRight -Administrator "$siteadminReadOnly" -Role "$siteroleReadOnly" -Scope "$siteScope"

Add secondary Delivery Controller to site

Log in to the secondary Delivery Controller and execute the following, from an elevated Powershell:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\XenDesktop\joinDDC02toSite.ps1

That’s it for the first part of the series. Next part will be posted next month. Thanks for reading. Feedback is always appreciated.