Jump to content
Welcome to our new Citrix community!
  • Unattended Citrix StoreFront Installation and Configuration


    cugcblogs

    chrisjeuckenrnd.png by Chris Jeucken, CTA

    About three years ago, I posted a blog about how to perform an unattended installation and configuration of Citrix StoreFront with Ivanti Automation. It did the installation, the creation of a new store and it added a second StoreFront server to the server group.

    Since most organizations are stepping away from (still awesome) tools like Ivanti Automation and are moving towards solutions like Puppet, Ansible, Chocolatey, Packer, plain PowerShell, etc., I wanted to create a PowerShell script that does the same, but does not require an automation tool.

    In this short blog, I will post how it works, how you can use it and of course the scripts themselves. Keep in mind that this is just an example, it is not a definitive solution for deploying StoreFront. Also, these scripts are not signed with a certificate because you need to enter your environment specific variables.

    These scripts have been tested with Citrix StoreFront 1912 Cumulative Update 2 on Windows Server 2019 (Build 17763.1697). I have divided it into three PowerShell scripts (contents and download link further down the page) which perform the following actions:

    SFScript-1-Install-StoreFront.ps1

    * Should be run on all StoreFront servers.

    - Add required Windows Features (with reboot if needed)

    - Install StoreFront (with reboot if needed)

    SFScript-2-Setup-Primary-StoreFront-Instance.ps1

    * Should be run on the first StoreFront server.

    - Create store

    - Create Receiver for Web Site

    - Create (self-signed) certificate

    - Bind certificate to site

    - Create redirect to Receiver for Web Site

    - Configure dedicated port for propagating (optional)

    SFScript-3-Join-Existing-StoreFront-Instance.ps1

    * Should be run on all subsequent StoreFront servers.

    - Get passcode from primary StoreFront instance

    - Join StoreFront server group with passcode

    - Propagate changes from primary StoreFront instance

    - Create (self-signed) certificate

    - Bind certificate to site

    - Copy redirect from primary StoreFront instance

    To use them, please follow these steps:

    1. Change the variable in script 1 that has the ‘EDIT’-comment behind them to a value that matches your environment.

    2. Run script 1 on all (planned) StoreFront servers.

    If a reboot is needed, you can run the same script after the reboot and it will simply skip the parts it has already done.

    3. Change all variables in script 2 that have the ‘EDIT’-comment behind them to values that match your environment.

    4. Run script 2 on the primary StoreFront server.

    5. Change the variable in script 3 that has the ‘EDIT’-comment behind them.

    This simply is the hostname, IP address or FQDN of the primary StoreFront server.

    6. Run script 3 on all subsequent StoreFront servers.

    Run it on one server at a time and not all at once.

    Good to know: You can define a specific port for propagating changes between the StoreFront instances. This is useful if these are in different subnets and the connection goes through a firewall. Otherwise you can leave it empty. It will then use a random port.

    Also beware that these scripts will create a self-signed SSL certificate. It is highly recommended to replace this with a proper SSL certificate.

    Script 1 – Install StoreFront

    # SCRIPT INFO -------------------# Script that installs Citrix StoreFront# Run on designated StoreFront server# By Chris Jeucken# -------------------------------# INSTALLATION VARIABLES --------    $SoftwarePath = "\\server\share\StoreFront 1912CU2" # <-- EDIT - Specify the folder where the CitrixStoreFront-x64.exe file is located (can also be a local folder)    $StoreFrontInstaller = "CitrixStoreFront-x64.exe"    $StoreFrontInstallerPath = $SoftwarePath + "\" + $StoreFrontInstaller# -------------------------------# PREREQUISITES -----------------# Set Stop on error	$ErrorActionPreference = "Stop"# Disable open file security warnings	$env:SEE_MASK_NOZONECHECKS = 1# -------------------------------# INSTALL FEATURES --------------    Import-Module ServerManager    $FeatureInstall = Install-WindowsFeature -Name Web-Default-Doc,Web-Http-Errors,Web-Static-Content,Web-Http-Redirect,Web-Http-Logging,Web-Filtering,Web-Basic-Auth,Web-Windows-Auth,Web-Net-Ext45,Web-AppInit,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Mgmt-Console,Web-Scripting-Tools,NET-Framework-45-ASPNET -Restart:$false    if ($FeatureInstall.ExitCode -eq "NoChangeNeeded") {        Write-Host "Required IIS Windows features already installed" -ForegroundColor Green    }    if ($FeatureInstall.ExitCode -eq "Success") {        Write-Host "Reboot needed for IIS Windows features installation." -ForegroundColor Magenta        Start-Sleep -Seconds 20        Restart-Computer -Force    }# -------------------------------# SCRIPT ------------------------# Check if StoreFront is already installed    if ((Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "Citrix*"}).Name -contains "Citrix StoreFront") {        Write-Host "Citrix StoreFront already installed." -ForegroundColor Green    } else {# Install StoreFront        Write-Host "Installing Citrix StoreFront." -ForegroundColor Green        $StoreFrontInstallerArguments = "-silent"        Start-Process -FilePath $StoreFrontInstallerPath -ArgumentList $StoreFrontInstallerArguments -Wait -PassThru        if ((Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -like "Citrix*"}).Name -contains "Citrix StoreFront") {            Write-Host "Citrix StoreFront installed. Rebooting server." -ForegroundColor Magenta            Start-Sleep -Seconds 20            Restart-Computer -Force        } else {            Write-Host "Citrix StoreFront installation failed." -ForegroundColor Red        }    }# -------------------------------

    Script 2 – Setup primary StoreFront instance

    # SCRIPT INFO -------------------# Script that sets up the first StoreFront instance# Run on designated (primary) StoreFront server# By Chris Jeucken# -------------------------------# CONFIGURATION VARIABLES -------# User defined variables    $SFBaseURL = "" # <-- EDIT - Define Base URL (e.g. https://storefront.local.lan)								      $XDDeliveryController1 = "" # <-- EDIT - Define primary Citrix VADs Delivery Controller (e.g. xddc1.local.lan)    $XDDeliveryController2 = "" # <-- EDIT - Define secondary Citrix VADs Delivery Controller (leave empty if there is only one Delivery Controller)    $StoreFriendlyName = "" # <-- EDIT - Define StoreFront store name    $XDFarmName = "" # <-- EDIT - Define Citrix VADs farm name    $SFCustomP2PPort = "" # <-- EDIT - OPTIONAL - Define port for propagating changes (leave empty for random port (default))# Pre-defined variables    $SiteID = 1    $StoreFriendlyNameWithoutSpaces = $StoreFriendlyName -replace '\s',''    $StoreFriendlyNameWithoutSpacesWeb = $StoreFriendlyNameWithoutSpaces + "Web"    $StoreVirtualPath = "/Citrix/" + $StoreFriendlyName -replace '\s',''    $StoreVirtualPathWeb = $StoreVirtualPath + "Web"    $StoreURL = $SFBaseURL + "/Citrix/" + $StoreFriendlyNameWithoutSpaces    $FarmType = "XenDesktop"    $TransportType = "HTTP"    $ServicePort = "80"    $SslRelayPort = "443"    $RedirectFile = "SFRedirect.html"    $RedirectPath = "C:\inetpub\wwwroot\"    $RedirectPage = $RedirectPath + $Redirectfile    $SFConfigFiles = "$env:ProgramFiles\Citrix\Receiver StoreFront\Services\SubscriptionsStoreService\Citrix.DeliveryServices.SubscriptionsStore.ServiceHost.exe.config",                    "$env:ProgramFiles\Citrix\Receiver StoreFront\Services\CredentialWallet\Citrix.DeliveryServices.CredentialWallet.ServiceHost.exe.config"# -------------------------------# PREREQUISITES -----------------# Set Stop on error    $ErrorActionPreference = "Stop"# Import StoreFront PS modules (not needed if using PoSH 3.0+, but just to be sure)	Import-Module Citrix.StoreFront	. "C:\Program Files\Citrix\Receiver StoreFront\Scripts\ImportModules.ps1"	Start-Sleep -Seconds 10# -------------------------------# SCRIPT ------------------------# Create initial store (will be deleted after creation of the definitive store)    Set-DSInitialConfiguration -HostBaseUrl $SFBaseURL `        -FarmName $XDFarmName `        -Port 80 `        -Transporttype HTTP `        -SslRelayPort 443 `        -Servers @("tempddc.domain.lan") `        -LoadBalance $false `        -FarmType "XenDesktop" `        -StoreVirtualPath /Citrix/TEMP `        -WebReceiverVirtualPath /Citrix/TEMPWeb# Create StoreFront store with one defined XenDesktop Delivery Controller    if ($XDDeliveryController2 -eq "") {        $AuthSummary = Get-DSAuthenticationServicesSummary -SiteID $SiteID        Install-DSStoreServiceAndConfigure -SiteID $SiteID `            -FriendlyName $StoreFriendlyName `            -VirtualPath $StoreVirtualPath `            -AuthSummary $AuthSummary `            -FarmName $XDFarmName `            -FarmType $FarmType `            -Servers @($XDDeliveryController1) `            -TransportType $TransportType `            -ServicePort $ServicePort `            -SslRelayPort $SslRelayPort        Install-DSWebReceiver -FriendlyName $StoreFriendlyName `            -SiteID 1 `            -StoreURL $StoreURL `            -useHttps $true `            -VirtualPath $StoreVirtualPathWeb    }# Create StoreFront store with two defined XenDesktop Delivery Controllers    if ($XDDeliveryController2 -ne "") {        $AuthSummary = Get-DSAuthenticationServicesSummary -SiteID $SiteID        Install-DSStoreServiceAndConfigure -SiteID $SiteID `            -FriendlyName $StoreFriendlyName `            -VirtualPath $StoreVirtualPath `            -AuthSummary $AuthSummary `            -FarmName $XDFarmName `            -FarmType $FarmType `            -Servers @($XDDeliveryController1,$XDDeliveryController2) `            -TransportType $TransportType `            -ServicePort $ServicePort `            -SslRelayPort $SslRelayPort        Install-DSWebReceiver -FriendlyName $StoreFriendlyName `            -SiteID 1 `            -StoreURL $StoreURL `            -useHttps $false `            -VirtualPath $StoreVirtualPathWeb        }# Create self signed certificate and bind it to site    if ($SFBaseURL -like "*https*") {# Remove https from URL         $SFBaseURLShort = ($SFBaseURL -replace "https://","")# Create self signed certificate        $Certificate = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname $SFBaseURLShort# Add certificate to Trusted Root Certification Authorities        $CertificateRootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList Root, LocalMachine        $CertificateRootStore.Open("MaxAllowed")        $CertificateRootStore.Add($Certificate)        $CertificateRootStore.Close()# Get certificate thumbprint        $Thumbprint = $Certificate.Thumbprint# Create new IIS binding        New-WebBinding -Name "Default Web Site" -IP "*" -Port 443 -Protocol https -Verbose# Add certiticate to IIS binding        Start-Sleep -Seconds 5        $Binding = Get-WebBinding -IPAddress "*" -Port 443 -Protocol https        $Binding.AddSslCertificate($Thumbprint, "my")    }# Create redirect to StoreFront site    Add-Content -Path $RedirectPage -Value "<script type=""text/javascript"">"    Add-Content -Path $RedirectPage -Value "<!--"    Add-Content -Path $RedirectPage -Value "window.location=""/Citrix/$StoreFriendlyNameWithoutSpacesWeb"";"    Add-Content -Path $RedirectPage -Value "// -->"    Add-Content -Path $RedirectPage -Value "</script>"    Add-WebConfiguration "system.webserver/defaultdocument/files" -atIndex 0 -Value $RedirectFile# Insert custom P2P port for propagating changes (otherwise it's random)    if ($SFCustomP2PPort) {        foreach ($SFConfigFile in $SFConfigFiles) {            if (Test-Path -Path $SFConfigFile -ErrorAction SilentlyContinue) {                $SFConfigFileContent = Get-Content -Path $SFConfigFile                $SFConfigFileContent | ForEach-Object {                    if ($_ -like "*net.p2p://*") {                        $_ -replace "`">",":$SFCustomP2PPort`">"                    } else {                        $_                    }                } | Set-Content -Path $SFConfigFile -Force            }        }    Restart-Service -Name CitrixSubscriptionsStore -Force    Restart-Service -Name CitrixCredentialWallet -Force    }# Remove initial store    Remove-DSStore2 -SiteID 1 -VirtualPath "/Citrix/TEMP"# -------------------------------​

    Script 3 – Join existing StoreFront instance

    # SCRIPT INFO -------------------# Script that adds a server to an existing StoreFront instance# Run on designated (secondary) StoreFront server# By Chris Jeucken# -------------------------------# CONFIGURATION VARIABLES -------# User defined variables    $SFExistingServer = "" # <-- EDIT - Define hostname or FQDN of primary StoreFront server# Pre-defined variables# Locations	$RemoteConfigFolder = "_CONFIG"	$RemoteConfigPath = "\\$SFExistingServer\c$"	$RemoteRedirectPath = "\inetpub\wwwroot\"	$LocalConfigFolder = "_CONFIG"	$LocalConfigPath = "C:"	$LocalRedirectPath = "C:\inetpub\wwwroot\"# Files and scripts	$RedirectFile = "SFRedirect.html"	$RemoteRedirectPage = $RemoteConfigPath + $RemoteRedirectPath + $Redirectfile	$RemotePasscodeScript = "$RemoteConfigPath\$RemoteConfigFolder\SFPasscodeScript.ps1"	$LocalPasscodeScript = "$LocalConfigPath\$LocalConfigFolder\SFPasscodeScript.ps1"# -------------------------------# PREREQUISITES -----------------# Set Stop on error	$ErrorActionPreference = "Stop"# Import StoreFront PS modules (not needed if using PoSH 3.0+, but just to be sure)	Import-Module Citrix.StoreFront	. "C:\Program Files\Citrix\Receiver StoreFront\Scripts\ImportModules.ps1"	Start-Sleep -Seconds 10# -------------------------------# SCRIPT ------------------------# Create PowerShell Session object for primary StoreFront server	$PSSession = New-PSSession -ComputerName $SFExistingServer# Check if folders and/or files already exist	if ((Test-Path $RemoteConfigPath\$RemoteConfigFolder) -eq 0 ) {		mkdir $RemoteConfigPath\$RemoteConfigFolder	}	if ((Test-Path $RemotePasscodeScript) -ne 0) {		Remove-Item $RemotePasscodeScript		}	if ((Test-Path $RemoteConfigPath\$RemoteConfigFolder\Passcode.txt) -ne 0) {		Remove-Item $RemoteConfigPath\$RemoteConfigFolder\Passcode.txt	}# Create script on existing StoreFront server	Add-Content -Path $RemotePasscodeScript -Value ". ""C:\Program Files\Citrix\Receiver StoreFront\Scripts\ImportModules.ps1"""	Add-Content -Path $RemotePasscodeScript -Value "Start-DSClusterJoinService"	Add-Content -Path $RemotePasscodeScript -Value "`$Passcode = (Get-DSClusterJoinServicePasscode).Response.Passcode"	Add-Content -Path $RemotePasscodeScript -Value "`$Passcode > $LocalConfigPath\$LocalConfigFolder\Passcode.txt"# Run script on existing StoreFront server	schtasks /Create /F /TN SFPasscodeScript /S $SFExistingServer /RU "SYSTEM" /TR "powershell.exe -File $LocalPasscodeScript" /SC once /ST 23:30	schtasks /Run /TN SFPasscodeScript /S $SFExistingServer	While ((schtasks /Query /TN SFPasscodeScript /S $SFExistingServer /fo List)[5] -notlike "*Ready") {		Write-Verbose -Message "Waiting on scheduled task..."	}	Start-Sleep -Seconds 5	$SFPasscode = Get-Content -Path "$RemoteConfigPath\$RemoteConfigFolder\Passcode.txt"	schtasks /Delete /TN SFPasscodeScript /S $SFExistingServer /F	Remove-Item -Path $RemoteConfigPath\$RemoteConfigFolder\Passcode.txt	Remove-Item -Path $RemotePasscodeScript# Join new server to StoreFront group and wait a while for completion	Start-DSClusterJoinService	Start-DSClusterMemberJoin -authorizerHostName $SFExistingServer -authorizerPasscode $SFPasscode	Start-Sleep -s 300	Invoke-Command -Session $PSSession -Scriptblock {		. "$env:ProgramFiles\Citrix\Receiver StoreFront\Scripts\ImportModules.ps1"		Stop-DSClusterJoinService	}	Start-Sleep -seconds 30	Stop-DSClusterJoinService# Propagate changes from existing StoreFront server	$PSSession = New-PSSession -computerName $SFExistingServer	Invoke-Command -Session $PSSession -Scriptblock {		Add-PSSnapin Citrix*		Start-DSConfigurationReplicationClusterUpdate -confirm:$FALSE	}	do {    	Write-Host "Waiting for StoreFront replication..." -ForegroundColor Magenta    	Start-Sleep -Seconds 60	} while ((Get-WmiObject -Class Win32_PerfFormattedData_PerfProc_Process -Property Name,PercentProcessorTime -Filter "Name LIKE 'Citrix.DeliveryServices.ConfigurationReplicationService%'").PercentProcessorTime -ne "0")# Create self signed certificate and bind it to site	$SFBaseUrlFull = Get-DSHostBaseUrl	$SFBaseUrl = $SFBaseURLFull.hostBaseUrl    if ($SFBaseURL -like "*https*") {        # Change URL to correct format        $SFBaseURLShort = ($SFBaseURL -replace "https://","")		$SFBaseURLShort = ($SFBaseURLShort -replace "/""")        # Create self signed certificate        $Certificate = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname $SFBaseURLShort        # Add certificate to Trusted Root Certification Authorities        $CertificateRootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList Root, LocalMachine        $CertificateRootStore.Open("MaxAllowed")        $CertificateRootStore.Add($Certificate)        $CertificateRootStore.Close()        # Get certificate thumbprint        $Thumbprint = $Certificate.Thumbprint        # Create new IIS binding        New-WebBinding -Name "Default Web Site" -IP "*" -Port 443 -Protocol https        # Add certiticate to IIS binding		$Binding = Get-WebBinding -IPAddress "*" -Port 443 -Protocol https		$Binding.AddSslCertificate($Thumbprint, "my")    }# Create redirect to StoreFront site	Copy-Item -Path $RemoteRedirectPage -Destination $LocalRedirectPath	Add-WebConfiguration "system.webserver/defaultdocument/files" -atIndex 0 -Value $RedirectFile# -------------------------------​

    DISCLAIMER: Once again: I’m in no way an expert PowerShell scripter, so it might not be the most efficient code, but it gets the job done. And, of course, feel free to use it/alter it/publish it as your own.

    Download scripts


    User Feedback

    Recommended Comments

    Can you please help us to install the Citrix storefront on the customized location like D or E drive thorugh powershell
    Link to comment
    Share on other sites

    Anil, for StoreFront itself it shouldn't be too hard. You only need to replace the following line in the first script and edit the prerequisites

     

    REPLACE

    $StoreFrontInstallerArguments = "-silent"

    WITH

    $StoreFrontInstallerArguments = "-silent -installdir 'D:\StoreFront'"

    (and change the path to what you want)

     

    But to change the location of the IIS website is a whole different story.

    And while it can be done, you would need to ask yourself: 'should you?'

    It will make everything more complex and installing everything on a secondary drive/partition seems a bit of a legacy approach. So why do you want to do this?

    Link to comment
    Share on other sites

    Guest Unattended Citrix StoreFront Installation and Configuration - ChrisJeucken.com

    Posted

    […] This blog was also posted on MyCUGC.org (link) on March 3rd, […]
    Link to comment
    Share on other sites



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

×
×
  • Create New...