Puppet – Deploying PVS 1912 CU1 Server Software Using Puppet

Puppet – Deploying PVS 1912 CU1 Server Software Using Puppet


Citrix Provisioning Services (PVS) is software streaming technology that delivers patches, updates, and other configuration information to multiple virtual desktop endpoints through a shared desktop image. It centralizes virtual machine management while reducing the operational and storage costs of a virtualized desktop environment.

Puppet is a Configuration Management tool that is used for deploying, configuring and managing servers. Puppet uses a Master Slave architecture in which the Master and Slave communicate through a secure encrypted channel with the help of SSL.

This article explains how to use Puppet to perform unattended installations of both the Citrix Provisioning Services server and console.

Test Environment

For this article I’ll be using an already deployed Puppet Master server on CentOS which has a very basic manifest configured to Domain Join any Windows machines when the puppet agent contacts the server.

My manifest files is named lab-setup.pp and is stored under /etc/puppetlabs/code/environment/production/manifests.

Active Directory is also configured in the environment with DNS and a network share created to hold the PVS installation files so that they can be called as part of the Puppet manifest directives.

The Provisioning Services Server itself is a flat install of Windows Server 2019 Standard Desktop Edition (GUI) which has already has the puppet agent installed, configured, and running on it. The server has also been joined to the Domain via puppet (see my article Creating A Domain Join Declaration For All Windows Machines for details on how to do this) and the DOT Net 4.5 Core feature applied as part of my standard OVF build for deploying servers through Bolt.

The Issue

Installing PVS server and the console silently is well documented in the current release product documentation below:


It’s straightforward enough to perform using the basic command line switches as shown below :

PVS_Server_x64.exe /S /v "/qn" 

The issue I encountered was when trying to pass the options through as it would always start the gui when I ran a puppet apply. I tried as a normal install_options setting, escaping the double quotes around /qn, and replacing the single quotes with double ones, and setting them as a variable which I then passed to the options but nothing worked. In the end I came across a page on the web about using square brackets to break out the options.

This finally worked and allowed me to deploy a new VM which joined the Domain and then installed PVS server without any interaction.

Installing Provisioning Services Server using Puppet

To install the Provisioning Services Server software using Puppet follow the steps below:

  • Connect to the Puppet server over SSH
  • Open the lab-setup.p file (I use vi as I’m on CentOS)
  • The First thing to do is declare the nodes this resource will apply to:
# LAB-PVS Servers Configuration

node /^(lab-halusky01|lab-halusky02).lab.lost-it.org$/ {
  • The next piece is to add the exec resources as follows:
package {'install-pvs-server':
 ensure => installed,
 subscribe => Class['domain_membership'],
 source => "\\lab-schnitzel\software\PVS-1912-CU1\Server\PVS_Server_x64.exe",
 install_options => [
   '/S /v',
  • The final piece is to add in a reboot as follows:
reboot {'pvsserver_reboot':
 message => 'PVS Install has requested a reboot',
 when => pending,
  • Save and exit the manifest file

Puppet Code Explanation

Below is a breakdown of the PVS Server install code piece by piece to show what means what and why it’s being used:

  1. node /^(lab-halusky01|lab-halusky02).lab.lost-it.org$/ { – Node declaration using pattern matching to apply to two different PVS servers
  2. package {‘install-pvs-server’: – Provides the package name which is shown in the puppet reports.
  3. ensure => installed, – Used to check that the software is installed and if not execute the install
  4. subscribe => Class[‘domain_membership’], – Subscribes to a previous class resource to ensure that PVS Server is only installed once the server has joined the domain.
  5. source => “\lab-schnitzel\software\PVS-1912-CU1\Server\PVS_Server_x64.exe”,
  6. install_options => [ – Defines the install options to be passed to the installer. The square bracket is used to allow specifying sets of options on different lines. The important part for using this method is that puppet will put double quotes around each of the following lines and separates them with a space.
  7. ‘/S /v’, – Sets the first two options which are passed by puppet as “/S /v”
  8. ‘/qn’, – Sets the quiet no gui options which are passed by puppet as “/qn”
  9. ], – Closes the square bracket used to define the install options.
  10. } – Closes the package function.

Final Thoughts

I’m still learning Puppet and finding my way around the different methods and code options so this is very much a first working attempt. There are community modules out there to do it but for me, I prefer to learn by doing !

Tested On

This piece of puppet code has been tested installing PVS Server 1912 CU1 LTSR on the following:

  • Windows Server 2019

Leave a Reply

Your email address will not be published.