In our previous 2 posts we have been dealing with introduction to DSC and LCM. If you missed those 2 posts, links below will get you to those 2 parts.

PART 1 – Desired State Configuration (DSC) – Get Started

PART 2 – Desired State Configuration (DSC) – Local Configuration Manager (LCM)

Before we go and configure our VMs, we need to cover something called CONFIGURATION DATA. It is important to understand this before we go into advanced configuration.

Desired State Configuration is designed with a DevOps mindset, and in the DevOps mindset, you want to be able to configure your development environment, your test environment and then your production environment using as much the same code as possible. So what you want to do is to have the configuration for each environment that you want to factor out the code that is specific to each environment, and then you want to have common code that’s common across them all, so Microsoft explicitly designed the feature to support that. The idea is to have structural information that is the same across the environments, and then configuration information. Configuration data is something that lives apart from the script itself, and is fed to the script when the script is run. You can confiure it as a separate file or you could have everything in one file. Basic configuration data looks like this.

The top level configuration data hash table needs to contain two elements, AllNodes and NonNodeData. AllNodes is an array, and it’ll contain all of the unique-to-each-node information that you need to provide. NonNodeData is a kind of “global” section and I will show you later how you can use this and why you should rename it.

NodeName = You can specify servername or you can specify IP address of the server

Role = That’s a property you can made up.  You can type in whatever word you like here (Instead of the word ROLE) but I recommend that you use ROLE. Same is for the value. You can specify whatever you like but I recommend that you type in the role you are installing, example if you are installing a domain controller, under ROLE you can type in DC or a domain controller.  So the ROLE property is data that’s only meaningful to me.2019-07-16 15_57_55-● Untitled-13 - Visual Studio Code [Administrator].png

To understand this, let’s say that we would like to configure RDS standard deployment with 3 servers. The top config data would look like this. I’ve defined three nodes, and for each, I’ve defined a “Role” property. These will be search tags and you will see later in this post where we are going to use them.

2019-07-17 09_55_05-● Untitled-13 - Visual Studio Code [Administrator].png

You will notice when we start to build our environment that we have properties that could apply to all hosts. So insted of typing the same value under each node we could use special All-Nodes Data node. It looks like this.

Now, all three of my nodes also have a PSDscAllowPlainTextPassword. This is exactly the same as if I’d manually listed that propertie for each node individually, but it saves some room. The * is a special character in this case; don’t think of it as a usual wildcard, because other wildcard expressions aren’t allowed. So all properties that will be applied to all hosts go under NodeName = ‘*’

2019-07-17 20_17_05-● Untitled-13 - Visual Studio Code [Administrator].png


A lot of people have problem with this section and I believe it is because of the word nonnodedata. The point of having this section is that it is good option for role-specific settings that do not pertain to all nodes. So you don’t want to put unique data for the machines under NodeName/Role. Example: If you are configuring DC, by unique data I mean dc log file path, domain name etc…

2019-07-17 23_23_04-● Untitled-13 - Visual Studio Code [Administrator].png

Let’s say that we want to configure rds deployment with 3 servers. In our top level config hash table we have nodename and the role and we want to keep that as small as possible. All unique data we will put under nonnodedata. Key to point is that you do not have to call the section “NonNodeData”, and second, you can have multiple NonNodeData sections. If you are configuring RDS, instead of NonNodeData you could call it RDSData or just RDS.


2019-07-17 23_31_37-● Untitled-13 - Visual Studio Code [Administrator].png

You may wonder how would you access data placed in “NonNodeData” or in this case RDSData? When you configure this, you will have the special $ConfigurationData variable, and $ConfigurationData.<NonNodeData> will access the “global” NonNodeData keys.

Let’s start with our configuration. I will not talk about configuration keyword and how to begin with the configuration. If you are not familiar with it, please check my first post about DSC.

The first problem I notice when people start with DSC is the Node $AllNodes.Where part…

2019-07-17 23_55_50-● Untitled-14 - Visual Studio Code [Administrator].png

The Node{} construct wants you to provide a list of node names. That’s it – just computer names, and no other data. So we’re taking $AllNodes, which contains everything. We’re using its special Where method to grab only those nodes whose Role property is set to Connection Broker. Remember that I made up the Role property, right? So I really could have filtered on any property that I’d put into the data block. Having done that filtering, I’m left with two nodes. Each node has a NodeName and a Role property – but the Node{} block here in the script only wants the names. So that’s why the “.NodeName” is there – it takes the filtered nodes and grabs just the contents of the NodeName property. Within the Node{} construct, PowerShell will automatically run the contents once for each node you’ve given it. It’s kind of like an invisible ForEach wrapped around the whole thing.

2019-07-18 00_01_19-● Untitled-14 - Visual Studio Code [Administrator].png


Let’s see in an example how would this look like. Is you can see under RDSData we have properties like Connection Broker, Session Host etc.

To access nonnodedata or in this case RDSData you would need to type in $data.rdsdata.connectionbroker. This could be very long specially if you use $configurationdata or any other longer word so I decided to place those values in a different variable called $RDData. Now I can type $RDData.ConnectionBroker which is much better.

2019-07-17 23_47_25-● Untitled-14 - Visual Studio Code [Administrator].png

2019-07-18 00_07_39-● Untitled-14 - Visual Studio Code [Administrator].png

When you are done with the configuration you would run it with configurationdata parameter.

2019-07-18 00_28_49-● Untitled-14 - Visual Studio Code [Administrator].png

Doing things like this (separating unique data from the Node/Role Section) will make your configuration much cleaner and it will be easier to maintain it. You could have multiple nonnodedata sections. One for DC, another one for DNS, DHCP RDS etc. We will see all of this in the future posts. In the next post we will build our environment from scratch.

I hope this has been informative for you.

Stay Tuned!