September 5, 2019

How to Install Hyper-V on Windows + Configure with Puppet

How to & Use Cases

Hyper-V is a helpful tool for creating virtual machines on Windows. We've written code and supported modules to make installing Hyper-V on Windows and configuring servers faster and easier.

In this blog, we'll outline installing and configuring Hyper-V on Windows with Puppet IT automation.

Table of Contents

What is Hyper-V?

Hyper-V is a hardware virtualization product from Microsoft for creating and running virtual machines.

How to Install Hyper-V on Windows with Puppet

Download the Right Puppet Modules

The example below because showcases a number of modules you'll need in order to manage your Windows servers, since some of the concepts in Windows will be fundamentally different from what you use in a Unix environment. These modules include:

  • puppet-windowsfeature: A module that will turn Windows features on or off for Windows Server 2008 and above.
  • hbuckle-powershellmodule: Allows PowerShell repositories to be registered as package sources and PowerShell modules to be installed using the Puppet Package type.
  • puppetlabs-dsc_lite: The Puppet dsc_lite module allows you to manage target nodes using Windows PowerShell DSC (Desired State Configuration) Resources.
  • nekototori-winrmssl: Setup WinRM over HTTPS and control some basic, essential settings. Also supports Puppet CA issued certificates.
  • puppetlabs-windows_puppet_certificates: A Puppet module to import the puppet certificates into the machine certificate store in Windows.

Enabling WinRM with SSL

WinRM is the native remote management solution for Windows, similar to SSH on Linux. We of course wanted to ensure that we were connecting to this Windows server securely, so we needed a way to manage an SSL certificate.

There are a few existing modules on the forge, but we decided to open source a new module, that more natively handled the importing of the Windows Certificates, without having to manage the passphrase in Puppet. This open-source module, built and tested by Puppet engineers and used internally by multiple teams, is available now.

Practical Uses for the Windows Puppet Certificate Module include:

  • Client certificate based authentication in EAP in 802.1x
  • Automatically trusting the PE Console in web browsers
  • Encrypting secrets for the client to consume, for example, Hiera eYaml
  • Encrypting secrets for the server to consume, for example encrypting Bitlocker keys
  • For example, you could use it to manage the certificates for SSL winrm

We enabled winrm, using the installed puppet certificate.

mod 'nekototori-winrmssl',                        '0.1.0'
mod 'puppetlabs-windows_puppet_certificates'      '0.1.0'

class profile::os::windows::winrm {
  class { 'windows_puppet_certificates':
    manage_master_cert => true,
    manage_client_cert => true,

  unless $facts['puppet_cert_paths']['ca_path'] {
    fail('The "puppet_cert_paths/ca_path" fact from the "puppetlabs-windows_puppet_certificates" module is missing')

  winrmssl { $facts['puppet_cert_paths']['ca_path']:
    ensure  => present,
    issuer  => $facts['puppet_cert_paths']['ca_path'],
    require => Windows_puppet_certificates::Windows_certificate['puppet_master_windows_certificate'],

Here we’re creating winrm, using the certificates installed by the “windows_puppet_certificates” module. Additionally, in order to catch the removal of the module without the removal of the custom fact, we check to ensure that the fact is defined and fail if it is not.

NIC Teaming

The server we were working on had four network interfaces, and one of our requirements was to create two bonded interfaces, each comprised of two of the regular interfaces. Along with this requirement, we needed to assign a static IP and gateway for just one of the bonded interfaces (the other one is used internally by Hyper-V). This part was accomplished with the puppetlabs-dsc_lite Puppet module, the “NetworkingDsc” Powershell module and some defined types.

We added these modules to our Puppetfile:

mod 'hbuckle-powershellmodule',                   '2.0.1'
mod 'puppetlabs-dsc_lite',                        '1.2.0'

We needed a class to install some dependencies:

class profile::network::windows_install_dsc_modules {

  pspackageprovider {'Nuget':
    ensure   => 'present',
    provider => 'windowspowershell',
    before   => Package['NetworkingDsc'],

  package { 'NetworkingDsc':
    ensure   => latest,
    provider => 'windowspowershell',
    source   => 'PSGallery',

...and a profile to configure the IP address and gateway (it uses the class above as a requirement):

define profile::network::windows_interface (
  Array[Stdlib::IP::Address]    $ipaddress,
  String[1]                     $interfacealias,
  Enum['IPv4','IPv6']           $addressfamily = 'IPv4',
  Optional[Stdlib::IP::Address] $gw_address = undef,

  include profile::network::windows_install_dsc_modules

  dsc {"${name}-ip-address":
    resource_name => 'IPAddress',
    module        => 'NetworkingDsc',
    properties    => {
      ipaddress      => $ipaddress,
      interfacealias => $interfacealias,
      addressfamily  => $addressfamily,
    require       => Class['profile::network::windows_install_dsc_modules'],

  if $gw_address {

    dsc {"${name}-default-gw":
      resource_name => 'DefaultGatewayAddress',
      module        => 'NetworkingDsc',
      properties    => {
        address        => $gw_address,
        interfacealias => $interfacealias,
        addressfamily  => $addressfamily,
      require       => Class['profile::network::windows_install_dsc_modules'],

Another defined type would configure the network bond and optionally set an IPaddress using the class above:

define profile::network::windows_nic_team (
  String[1]                                                                  $nic_name,
  Array[String]                                                              $teammembers,
  Enum['SwitchIndependent','LACP','Static']                                  $teamingmode = 'SwitchIndependent',
  Enum['Dynamic','HyperVPort','IPAddresses','MacAddresses','TransportPorts'] $loadbalancingalgorithm = 'HyperVPort',
  Enum['IPv4','IPv6']                                                        $addressfamily = 'IPv4',
  Optional[Array[Stdlib::IP::Address]]                                       $ipaddress = undef,
  Optional[Stdlib::IP::Address]                                              $gw_address = undef,

  include profile::network::windows_install_dsc_modules

  dsc {$name:
    resource_name => 'NetworkTeam',
    module        => 'NetworkingDsc',
    properties    => {
      name                   => $nic_name,
      teamingmode            => $teamingmode,
      loadbalancingalgorithm => $loadbalancingalgorithm,
      teammembers            => $teammembers,
    require       => Class['profile::network::windows_install_dsc_modules'],

  if $ipaddress {

    profile::network::windows_interface { "set-ip-${name}":
      ipaddress      => $ipaddress,
      gw_address     => $gw_address,
      interfacealias => $nic_name,
      require        => Dsc[$name],

Putting these all together, we just needed to add this to our main profile class which configures both bonded interfaces:

 profile::network::windows_nic_team { 'nic_team1-HyperV':
    nic_name    => 'Team1 - HyperV',
    teammembers => ['NIC1', 'NIC2'],

  profile::network::windows_nic_team { 'nic_team2-Vlan22':
    nic_name    => 'Team2 - VLAN 22',
    teammembers => ['NIC3', 'NIC4'],
    ipaddress   => [''],
    gw_address  => '',

Enabling Hyper-V

In order to install Hyper-V on Windows, we need to be able to manipulate Windows features. To do this we’ll use the puppet-windowsfeature module from the Puppet Forge. This module was also created by engineers at Puppet in collaboration with the Vox Pupuli module writing collective.

class profile::windows::hyperv {
 windowsfeature { 'Hyper-V':
   ensure => present,

 reboot {'after_Hyper_V':
   when      => pending,
   subscribe => Windowsfeature['Hyper-V'],


Learn More