Published on 17 February 2016 by

In the first post in this blog series, we installed the newly supported DSC module in Puppet and talked about some of the things that make doing so awesome. For this next installment, I’d like to take that a step further and start writing some Puppet code using DSC to showcase the power of using them together in a Windows environment.

First things first though, a common question we get is when to use Puppet, and when to use DSC. In the first post, we talked about some of the similarities they share on the surface. They are both declarative tools that can manage files, create users, services, etc. The way I look at it, DSC is an augmentation to an already powerful framework that Puppet provides us. When I’m writing Puppet code, the thing I try to stay away from the most is having to use the exec resource. Even though Puppet fully supports this in the product, execs aren’t ideal for a couple of reasons:

  • Execs aren’t idempotent by nature. You have to create conditionals to prevent the code from running on each Puppet run. These tests can be timely to write and error prone (especially when I write them!).
  • If my exec is doing lots of things, like maybe I’m executing a .bat file or a script, I don’t get the visibility into what that script actually did. I can see from the Puppet reports that it was able to run the script, but did all the things the script was doing (or supposed to do) actually happen? Did it fail on some systems and throw an error code that Puppet didn’t catch?
  • Is the exec causing performance issues on the agent. Is it running longer than expected? Is it holding up the rest of my Puppet run?

These are just a few things that come to mind and the main reasons I do everything in my power to avoid using them. For me, DSC allows me to do exactly that — avoid execs. Trying to write some Puppet code to manage a Windows service and need to set the Run As account username and password? No problem with DSC! Again, to me, Puppet and DSC are like two puzzle pieces that fit together and augment each other really well to tell a single, fluid story. But enough talking, let’s write some code!

In my first post, we talked about installing the DSC module, so I’m going to assume that the module is installed on your Puppet Master. For this example, I’ll be using Chocolatey as well, so make sure you have chocolatey/chocolatey installed. I have a few Windows Server 2012 R2 machines with the Puppet agent pre-installed, which I’ll be using for testing.

Let’s start by building a baseline profile. I think of baseline profiles as being a Puppet manifest that describes a set of baseline settings and applications that I want on a machine regardless of its end function, be that a web server, database server, etc. For more information on the Roles and Profiles design pattern, check out this link.

I’m going to assume that you already have a profile and role module set up on your Puppet Master. If you don’t you can simply make the profile/manifests and role/manifests directories on your master, or use the Puppet Module tool to make them for you.

Within that manifests directory we’re going to make a file called baseline.pp:

class profile::baseline {


Now let’s identify a few things that we want in our baseline. First, we want to make sure we have the latest version of PowerShell so we can use DSC (duh!). Second, we want to set up some RDP settings, create a user, and manage some services.

Building those things in, I now have something like this:

class profile::baseline {

  package { '7zip':
    ensure => installed,
    provider => 'chocolatey',

  package { 'git':
    ensure => installed,
    provider => 'chocolatey',

  reboot { 'afterpowershell':
    when    => pending,
    timeout => 15,

  service { 'wuauserv':
    ensure => 'running',
    enable => 'true',
  } ->

  package { 'powershell':
    ensure   => latest,
    provider => 'chocolatey',
    install_options => ['-pre'],
    notify => Reboot['afterpowershell'],
  } ->

   dsc_user { 'User account for Spencer': 
    dsc_ensure                   => 'present',
    dsc_username                 => 'spencer_dsc',
    dsc_description              => 'user account for Spencer with DSC',
    dsc_passwordchangerequired   => 'true',
    dsc_passwordneverexpires     => 'false',
    dsc_passwordchangenotallowed => 'false',
    dsc_disabled                 => 'false',
    dsc_fullname                 => 'Spencer Seebald',
  } ->

  dsc_group { 'Administrators group':
    dsc_ensure      => 'present',
    dsc_groupname   => 'Administrators',
    dsc_description => 'Builtin Administrators Group',
    dsc_memberstoinclude     => ['spencer_dsc','vagrant'],
  } ->

  dsc_xremotedesktopadmin {'Disable RDP NLA':
    dsc_ensure => present,
    dsc_userauthentication => 'NonSecure',


All we have to do now is classify our Windows machines with the manifest we just created. If you’re using Puppet Enterprise, this can be done through Hiera or through the web UI.

And we’re done! We now have a fully functioning baseline profile which incorporates DSC and Puppet to give us a good foundation to build on. We’re also using a mix of Puppet resources and DSC resources together — we'll continue using this pattern as we keep building on this base. Stay tuned for the next installment of this DSC blog series where we’ll layer on some additional functionality and turn these machines into something really cool, like web servers. Eventually we’ll have enough to make a role, which will be the all-encompassing thing we’ll apply to a machine for full configuration.

Learn more

Share via:

Add new comment

The content of this field is kept private and will not be shown publicly.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.