This project is a small set of Rake tasks to automate the process of building MSI packages for Puppet on Windows systems.
This is a separate repository because it is meant to build MSI packages for arbitrary versions of Puppet, Facter and other related tools.
This project requires these tools from the puppetwinbuilder
Dev Kit for Windows systems.
- Ruby
- Rake
- Git
- WiX
Download the Puppet Win
Builder archive, and unzip into C:/puppetwinbuilder/
. Once extracted, execute the
setup_env.bat
script which will update your PATH to include the
necessary tools, e.g. git, wix (heat, candle, and light), etc.
C:\>cd puppetwinbuilder
C:\puppetwinbuilder>setup_env.bat
C:\puppetwinbuilder>cd \work
C:\work>git clone git://github.com/puppetlabs/puppet_for_the_win
C:\work>cd puppet_for_the_win
C:\work\puppet_for_the_win>rake -T
Puppet For The Win composes an MSI from several different repositories. You will need to specify a configuration file to build it.
To build Puppet agent:
C:\work\puppet_for_the_win>rake windows:build AGENT_VERSION_STRING=1.0.0 CONFIG=foss-stable.yaml
The following MSI public properties are supported:
INSTALLDIR
"%ProgramFiles(x86)%\Puppet Labs\Puppet"
PUPPET_MASTER_SERVER
"puppet"PUPPET_CA_SERVER
Unset, Puppet will default to usingPUPPET_MASTER_SERVER
PUPPET_AGENT_CERTNAME
Unset, Puppet will default to usingfacter fqdn
PUPPET_AGENT_ENVIRONMENT
"production"PUPPET_AGENT_STARTUP_MODE
"Automatic"PUPPET_AGENT_ACCOUNT_DOMAIN
UnsetPUPPET_AGENT_ACCOUNT_USER
"LocalSystem"PUPPET_AGENT_ACCOUNT_PASSWORD
Unset
To install silently on the command line:
msiexec /qn /l*v install.txt /i puppet-agent.msi INSTALLDIR="C:\puppet" PUPPET_MASTER_SERVER="puppetmaster.lan"
Note that msiexec will execute asynchronously. If you want the install to execute synchronously on the command line, prepend start /w
as follows:
start /w msiexec /qn ...
The installer preserves configuration settings during an upgrade. If you override a value on the command line, it will overwrite the previous value in puppet.conf, if any.
The PUPPET_AGENT_ACCOUNT_*
settings are exceptions, as they must be specified each time you install or upgrade (since we do not want to save the credentials in the registry).
Every Puppet MSI contains:
- unique PackageCode
- unique ProductCode, so that we always perform Major upgrades.
- the same UpgradeCode
A major upgrade means that an upgrade will remove the old product and install the new one. However, we want to preserve settings, such as the Service startup type (Automatic, Manual, etc).
As a result, we use the "RememberMe" pattern to preserve settings. The flow works like this for an arbitrary MSI public property PUPPET_FOO
:
PUPPET_FOO
is defined.- Windows installer sets
PUPPET_FOO
to the command line value, if one was specified. - Before AppSearch, the
SaveCmdLinePuppetFoo
custom action setsCMDLINE_PUPPET_FOO
to the current value ofPUPPET_FOO
. - In AppSearch,
PUPPET_FOO
is set to the value of the RememberMe property in the registry, if any. - After AppSearch, the
SetFromCmdLinePuppetFoo
custom action setsPUPPET_FOO
to the value ofCMDLINE_PUPPET_FOO
. - In RegistryEntries, the value of
PUPPET_FOO
is written to the registry.
Note that if a value is specified on the command line, it takes precedence over the previously remembered value.
Note the property as defined in step 1 should not have a defaut value, otherwise, it will always take precedence over the remembered value, which would break upgrades.
The remembered properties are written to the registry in two locations:
HKLM\Software\Puppet Labs\Puppet
HKLM\Software\Puppet Labs\PuppetInstaller
On x64 systems, this is a redirected registry path:
HKLM\SOFTWARE\Wow6432Node\Puppet Labs\Puppet
HKLM\SOFTWARE\Wow6432Node\Puppet Labs\PuppetInstaller
Information specific to working with with Properties and conditionals is available at Using Properties in Conditional Statements
The CustomAction can be conditional using the syntax defined at Conditional Statement Syntax Here's an example used in the Remember Property Pattern
<Custom Action='SaveCmdLineInstallDir' Before='AppSearch' />
<Custom Action='SetFromCmdLineInstallDir' After='AppSearch'>
CMDLINE_INSTALLDIR
</Custom>
In this example the SaveCmdLineInstallDir
will act unconditionally while the SetFromCmdLineInstallDir
action will act only when the CMDLINE_INSTALLDIR
property is set.
This technique can be used to conditionally set properties that aren't explicitly set by the user.
The strings used throughout the installer are defined in the file
wix/Localization/puppet_en-us.wxl
. In the future if we support other
languages than English we will need to create additional localization files. A convenient place to get started is the WiX source code in the src/ext/UIExtension/wixlib/*.wxl
directory.
For the time being, any customization of strings shown to the user needs to happen inside of puppet_en-us.wxl
.
In addition, customization of text styles (color, size, font) needs to have a new TextStyle defined in wix/include/textstyles.wxi
Start Menu Shortcuts are provided to online documentation. The method we're employing to create these links is a little strange. We are not using the InternetShortcut Element because this element does not allow us to add a description or an Icon.
Instead, we use the IniFile Element to write out a file with a .url
extension into the documentation folder of the installation directory. We then create traditional shortcuts to these special .url
files. This allows us to add a description and an Icon to the shortcut entry.
Digitally signing the MSI is important for release. Windows will automatically verify the authenticity of our packages if they're signed and will present a warning to the user if they're not.
Here's the less scary notification when installing a signed package:
To digitally sign the packages, the Puppet Labs Code Signing Certificate should be installed into the user store on the windows build host. If Jenkins is being used to automate the package builds, then this certificate and private key should be installed using the same account the Jenkins agent is running as.
There should only be one code signing certificate installed. The signtool
will automatically select the right certificate if there is only one of them installed.
Double clicking on the PFX file will install the certificate properly. I also recommend the certificate NOT be marked as exportable when installing it.
Once the MSI packages have been built, they can be signed with the following task:
Z:\vagrant\win\puppetwinbuilder\src\puppet_for_the_win>rake windows:sign
signtool sign /d "Puppet" /du "http://www.puppetlabs.com" /n "Puppet Labs" \
/t "http://timestamp.verisign.com/scripts/timstamp.dll" puppet-agent.msi
Done Adding Additional Store
Successfully signed and timestamped: puppet-agent.msi
The command the Rake task is executing will require HTTP Internet access to timestamp.verisign.com in order to get a digitally signed timestamp.
The Sign Tool is distributed as part of the Windows
SDK You don't need to install the full SDK to get signtool.exe
, only the "tools" component. The SDK requires the Microsoft .NET Framework 4 to be installed as well.
The puppetwinbuilder.zip setup_env.bat
should automatically add the SDK to the PATH. If the SDK changes versions in the future (e.g. 7.2 is released), then the PATH environment variable may not be correct and you'll need to get signtool.exe in the path yourself or update the puppetwinbuilder.zip file.
If you receive exit code 128 when running rake build tasks and it looks like candle
and light
don't actually do anything, it's likely because the Microsoft .NET Framework is not installed.
If you try to run candle.exe
or light.exe
from Explorer, you might receive "Application Error" - The application failed to initialize properly (0xC0000135). Click on OK to terminate the application. This is the same symptom and .NET should be installed.
In order to resolve this, please use Windows Update to install the .NET Framework 3.5 (Service Pack 1).
To get a shared filesystem:
net use Z: "\\vmware-host\Shared Folders" /persistent:yes
EOF