Digging into the Replica Domain Controller ARM Template Code

If you are here because you want some built into your world vs. manual builds + configuration, then you've arrived at the right place! Two hot topics come into view when discussing ARM Templates: and Infrastructure as Code. is an engineering process for maintaining consistency of workloads throughout their lifecycle. Typically, is deployed through code. Infrastructure as Code is the management and provisioning of infrastructure via code versus performing manual tasks to build systems. With increased Azure adoption, using both methodologies to build and configure infrastructure + related applications meet the speed, agility, and scale of cloud computing. ARM Templates are JSON files that enable infrastructure as code for Azure Resource Manager. Azure is managed using APIs and the resources ARM APIs manage are objects in Azure such as cards, virtual machines, hosted databases, etc.

Usually when I get to this point in the discussion, I either have folks who 100% understand what I'm talking about OR I have the exact opposite and a lot of “deer in headlights” looks. If you fall in the “deer in headlights” category, I wanted to pass along some good links to get yourself up to speed on ARM Templates:

ARM Template Reference
Structure and Syntax of ARM Templates
ARM Template Best Practices
Azure Quickstart ARM Templates – GitHub

Azure Resource Manager Templates Quick Start Guide
Quick and Practical Guide to ARM Templates

World Class ARM Templates

Mastering Microsoft Azure Resource Manager
Azure Master Class: Manage Azure Cloud with ARM Templates

Blog Series (I authored these posts)

An Intricate Look at ARM Templates – Part 1
An Intricate Look at ARM Templates – Part 2
An Intricate Look at ARM Templates – Part 3
An Intricate Look at ARM Templates – Part 4

Without further ado, I bring you my template code to start noodling through:


In similar fashion to ARM Templates you may find in the Quickstart repo, there is a azuredeploy.json and an azuredeploy.parameters.json. In the ARM Template world, you typically leave your parameters for values that may need to be changed over time (i.e. Windows OS version, static IP addresses, names of VMs, etc.). Your variables are more static entries that will not change as often (if ever). Using this template should be as straightforward as cloning the repo locally and adjusting the parameter file to deploy using Visual Studio, PowerShell, or the Azure CLI. If you recall my pre-requisites mentioned you would need an existing virtual , an existing site-to-site (or ExpressRoute), and the virtual would need line of site to on-premises for DNS resolution, domain joining, and promotion. In addition, a Key Vault needs to be set up (don't forget that piece and use the parameters file as a way to understand how to plug in a Key Vault secret for certain sensitive information about your environment like a local administrator password or a domain administrator password).

The template itself will build out 2 Windows VMs with managed disks, a non-cached data disk for sysvol, and places both VMs into an availability set. After the VMs are built, the template also leans on a desired state configuration (DSC) extension that I will blog about in my next post (mainly because DSC is a tad complicated, but it's pretty darn effective). Note, the DSC extension is the piece that formats the data disk, joins the VM to the existing domain, installs the Active Directory role, and promotes the replica domain controllers.

During initial phases of testing this template, I actually had 2 VMs, 2 nics, and 2 DSC extensions declared as resources in the resources section. Upon discussion with one of my favorite ARM Template gurus (I'd love to do a special shoutout to Matt Canty for his willingness to brainstorm and break down some of the more complex pieces of ARM Templates + DSC in ways that everyone can understand, not just devs), he asked if there could be an easier way to think through my configuration. He brought up the idea of using copyIndex and concat (sort for concatenate). copyIndex is a numeric function that simplifies resource iteration in ARM Templates (definitely make sure to click on that link so you understand exactly what the ARM Template function is doing). copyIndex allowed me to declare 1 VM resource in the template, along with 1 DSC extension, and 1 nic, while specifying the amount of copies I needed to create in the template. The copyIndex configuration really copies the same configuration into 2 instances using the way I wrote the template (coupled with some of Matt Canty's careful tutelage). concat combines multiple arrays or string values and returns the concatenated string or array as a name. Using this function added slight complexities with names, but helped achieve the overall idea of simplifying the template with 1 resource declared vs. multiple VMs, nics, and DSC extensions.

So what does this mean? Let's first look at the nic configuration and compare it with the VM configuration later in the post.


I highlighted where the copyIndex and copy count information show up. I declare the resourceCount is 2 in the parameters section (you could increase that if your environment requires more replica domain controllers). The padLeft allows for the nic name to use the dcNicName in variables and add 01 and 02 after. The nic name becomes azdc-nic01 and azdc-nic02 if you take my template as-is, but you can experiment with names as you work on automating your replica domain controller build. The private IP addresses are passed as an array (arrays live within brackets []) within the parameters file (and would need to be pre-populated). Here is what they look like within the parameters file:

"ipAddresses": {
      "value": [

Now, for the VM, let's look at the way the copyIndex works in declaring that resource.


I've highlighted more of how to use the copyIndex with concat and padLeft, which adds 01, 02, etc to the name. Note, copyIndex occurs with the domain controller name, the disk names, and the nic names. Additionally, the VM creation depends upon nicloop (the name of the nic creation using copyIndex). So copyIndex reduces complexity from having multiple resources being configured the same way and deploys multiple resources with the same configuration, based upon a copy number you indicate within the parameters file. copyIndex is a more advanced function in my humble opinion, so my recommendation would be to experiment with this template a bit and ensure it gives you everything you are looking for.

For my next post, I will move into talking about desired state configuration (DSC) and how that works on all the post build configuration steps for a replica domain controller. If you have any questions or comments, definitely feel free to reach out!


This article was originally published by Microsoft's Premier Field Engineering Blog. You can find the original article here.