Building a disposable Windows 2016 domain controller in 20 minutes with Vagrant

Building infrastructure for Windows, SQL Server or SharePoint is not an easy task. It involves dozens of files to be downloaded, several dozens of configurations, several virtual machines, and hours of work.

Wouldn’t it be great just to run a few commands, and end-to-end setup happens automatically? With the recent patches, updates and minimal configurations? And the ability to execute your scripts on top? And also run this on Windows/MacOS, and under CI/CD pipelines?

Get into this blog post and learn several useful skills:

  • Really quick, hands-on intro on Vagrant

There is no manual steps, wizards or screenshots. We value your time offering a scalable and highly repeatable solution for your team or the whole company.


Introducing The Uplift project

This post shows how you can create a disposable Windows 2016 domain controller in 20 minutes with no manual interventions.

There is no manual steps, wizards or screenshots. We value your time and offer a scalable solution for your team or the whole company — this is a fully automated and hence scalable Packer/Vagrant workflow which can be run on Windows/MacOS laptops, on Windows 2008, 2012, 2016, in the cloud, share with the team or integrate into CI/CD pipelines.

This post also continues a mini-series on The Uplift project — a Packer/Vagrant toolkit for SharePoint professionals more details on which you can find below:

So let’s start building!

Fast forward to Packer/Vagrant

With the increasing complexity of the infrastructure builds and software engineering, the right tooling and automation is a crucial contributor to the overall project success. Automation and tooling can save hours of work, lower down internal cost, help to deliver more features, and maybe most important — improve the team's moral and happiness.

When it comes to baking virtual machine images and managing Virtual machines, there might be no better tool than HashiCorp’s Packer and Vagrant by HashiCorp.

In a nutshell, Packer provides an easy way to create any type of machine images, including Sysprep-ed Windows images for Hyper-V, VirtualBox, Azure, Amazon and many others.

More details on why to use Packer and its benefit can be found on the official Packer web site:

Vagrant is another tool by HashiCorp which comes handy while building development, test or lab virtual machine environment.

More details on why to use Vagrant and its benefit can be found on the official Vagrant web site:

Altogether, Packer/Vagrant reduce the complexity of dealing with low-level details of virtual machine image builds, creating and configuring virtual machines and other useless tasks. In return, we have more time to work on features rather than fighting boring and never-ending issues.

In more details, we described how’s and why’s we use Packer/Vagrant in the Uplift project in the previous post. Feel free to park it for later read.

Installing Vagrant

Getting started with vagrant is super-easy. You can use the Chocolatey package manager or download the installaation package from the Vagrant site itself:

With Chocolatey, we write a quick recap on how it can be used. Simply run the following and enjoy the result. You might also be asked to reboot.

choco install -y vagrant

With manual installation, Vagrant comes as a standard windows package asking for a few “Next” clicks.

By default, Vagrant comes with VirtualBox. That makes it easier to run virtualized environment on various platforms including Windows 2008, Windows 10, Windows 2016 and MacOS. There is a decent level of automation support for VirtualBox, and therefore we choose to use it.

Be aware that for Windows platform you might have to disable Hyper-V in order to make VirtualBox work. This is an unfortunate compromise, Hyper-V or VMware support in the Uplift project might come later. Give us a shout if you need one.

Testing Vagrant install

Checking Vagrant version

First thing first, so let’s see if we have vagrant installed right. Load your terminal and execute the following:

vagrant --version

It should go without errors and print the current Vagrant version installed. Vagrant CLI comes with tons of commands which you can find here:

Introducing and exploring Vagrant Cloud

A good thing about Vagrant is that virtual machine images can be shared on the so-called Vagrant Cloud.

See Vagrant Cloud as a NuGet or PowerShell Gallery but for virtual machine images. How cool is this, really?

Variant Cloud contains thousands of ready-to-use virtual machine images. Linux, MacOS, Windows, you name it! We highly suggest to explore it but a few notable images are these. Let us know which your favourite ones are.

There is also a bunch of Linux based images, such as CentOS, Ubuntu, Barge and others. There are some with Jenkins CI/CD server pre-installed!

Creating your first virtual machine with Vagrant

At this point, we should have vagrant installed and be familiar with vagrant Cloud. Pick up an image or use Bargee (because it is super-small) or early mentioned images to get started.

Every image in Vagrant Cloud has a name, Vagrantfile example and “New” examples. Here is how it all fits together:

  • Vagrantfile defines how to create and configure the virtual machine

Let’s create a project folder, then go there and execute a few commands. You can use PowerShell but it also works in CMD terminal too:

Once done, you should have a Vagrantfile within this folder. Now we can run Vagrant commands to create and manage the virtual machine. Create a new machine and check out your VirtualBox, you’ll see VM there.

Check out your VirtualBox, here is the virtual machine Vagrant created.

As you can see, Vagrant makes virtual machine management super-easy. Give it a go with different images and explore Vagrant further.

Default credentials for Vagrant virtual machines

Usually, Vagrant boxes come with the default user vagrant name and password vagrant. This is a responsibility of the authors while creating boxes, it should come with the vagrant user to enable Vagrant interaction with the VM.

Most of the time, this should work well for Windows boxes. You can also leverage Vagrant CLI to login into the box with corresponding commands if the box was configured properly:

At this point, you should be able to:

  • Ensure that Vagrant works

Well done! With such knowledge, you should already have some big ideas! Let’s keep moving and see how we can turn virtual machines into something meaningful.

Provisioning Vagrant virtual machines with scripts

At this point, we already know how to find needed virtual machine image on Vagrant Cloud and how to create and manage new virtual machines.

Time to learn how we can apply PowerShell scripts against newly created virtual machines. Vagrant provides an easy way to execute scripts, apply Puppet, Ansible and other configuration management systems against virtual machines. This is how the provisioning workflow can be automated and codified via Vagrantfile.

Switching the base box

Pick up the Windows box, create a new project or edit existing Vagrantfile pointing to this box. You can use any Windows box from the Vagrant Cloud but you might also want to start using our boxes designed for SharePoint workloads:

Once done, execute vagrant up to ensure all things work. You should have a working Windows Server 2016.

vagrant destroy --force
vagrant up

Vagrant check if the image exists locally and downloads it from the Vagrant Cloud if needed. Here is how it looks like in Cmder:

vagrant up in action — Vagrant gets the image and creates a virtual machine.

Adding PowerShell provisioner

Open up the Vagrantfile again. At the very bottom, you can see the “provision” section:

This is how Vagrant knows which scripts to execute against target virtual machine. Out of the box, Vagrant supports dozens of provisioners including Fule, Shell, PowerShell, Chef, Ansible, Puppet and others. Open-source plugins also bring support for PowerShell DSC, Pester and

There are several ways to configure this but we’ll focus on PowerShell iterating and improving every run. In our case, we are going to use in-place script and external script to demonstrate how scripting can be done:

Using shell provision with in-line PowerShell scripts

This is a quick and dirty way to add scripts into Vagrantfile itself. Good for testing and fast prototyping but might not fit advanced scenarios.

Uncomment “shell” provisioner and add the following PowerShell script to output hostname, OS name and installed products:

Once done, execute vagrant up with provision flag. By default, all vagrant provisioners are run once during the virtual machine lifecycle. provision flag tells Vagrant to enforce provisioners against the already provisioned virtual machine.

vagrant up --provision

The output should look like this. Pretty cool, huh?

Using shell provision with external PowerShell scripts

At this stage, you should already see how Vagrant makes the whole provisioning process automated and highly enjoyable. With Shell provisioner, you can execute PowerShell scripts against virtual machines with little to no effort!

The next step is to decouple the PowerShell script from the Vagrantfile itself. Provisioner can use the file path to pick up the right PowerShell script so that you can manage and develop PowerShell in the external file.

Create “get-system-info.ps1” file in the same folder with the following content. Two points to be aware of:

  • Fail script early, with $ErrorActionPreference = “Stop”

Vagrant configuration for this provisioners becomes trivial. Now you can develop scripts separately from Vagrantfile!

Execute the familiar vagrant up and enjoy the result:

vagrant up --provision

Reconfiguring hardware: CPU and RAM

Quick bonus point. Among many other configurations, Vagrant provides an easy way to change virtual machine CPU and RAM. In case of VirtualBox, here is the full list of settings:

A ready to use snipper is this one:

Execute vagrant reload to apply these settings against a virtual machine:

vagrant reload

Check out VirtualBox, the outcome is now 4Gb with 4 CPU. No manual intervention is needed.

Building a disposable Windows 2016 domain controller in 20 minutes with Vagrant

Hey, you did well!

Not only you already learn Vagrant, can quickly create virtual machines and apply PowerShell scripts against them, but now you have all the knowledge to move to bigger things — you own ideas or our ready-to-use automation.

More or less, you have an idea of how Vagrant works:

  • There are pre-provisioned, pre-configured base boxes in Vagrant Cloud

With the Uplift Project, we implemented additional automation:

  • Vagrant base boxes for Windows 2016 and others

This is how we can create a new virtual machine and turn it into a domain controller really quickly.

1/3 — Get SubPointSolutions/win-2016-datacenter-app box

At this point, you should already have “SubPointSolutions/win-2016-datacenter-app” box downloaded but if you don’t just review the previous paragraph on PowerShell scripts. Let’s get the second bit, the Vagrant plugin and see what it offers.

This box comes with the latest windows patched available on the release date, .NET35 and some PowerShell modules which we need for simple configuration later on. Full details on what’s in the box can be found on Vagrant Cloud:

2/3 — Installing a vagrant-uplift plugin

Vagrant itself is written in Ruby and comes with a variety of open-source plugins. The easiest way to explore these are either via rubygems.org or documentation on the GitHub:

Our plugin is called vagrant-uplift, it provides a simplified configuration of DC, SQL, SharePoint and VS and designed to be used with uplift packer boxes. It is open-source and more details can be found on the GitHub:

Installing vagrant plugins is super-easy:

vagrant plugin install vagrant-uplift

listing installed plugins can be done as well:

vagrant plugin list

3/3 — Configuring Windows 2016 domain controller with the vagrant-uplift plugin

You should be already familiar with Vagrantfile configurations but if you don’t just review the previous paragraphs. Time to configure a new domain controller with the help of the vagrant-uplift plugin.

Here is the full configuration which can also be found in the GitHub:

This configuration is pretty self-explanatory. Helper methods are exposed via Ruby class VagrantPlugins::Uplift::Config() and organized into two subsets receiving box name and vagrant box config parameters Full documentation on methods and parameters can be found on the GitHub:

Execute vagrant up or vagrant up with provision flag and enjoy the newly created domain controller. You can notice information messages coming from the vagrant-uplift plugin:

vagrant up; with the uplift-vagrant plugin.

Later on, you can see initial provisioning done, then PowerShell DSC configuration for the domain controller gets executed, and then reboot completes domain controller.

Provision is split into several steps:

  • Configure virtual machine CPU/RAM

All steps come as a Vagrant helper; both provision and Pester execution is written in PowerShell and PowerShell DSC behind the scenes.

Here is how vagrant-uplift plugin configures basic settings and executes Pester tests at the end — we ensure that needed windows features are turned on, registry settings present and so on.

This ensures high quality and consistency of every setup.

During provision, we also check that a few tools are installed, such as 7z, wget/curl, the firewall is off (this is dev, test and lab env!), and other settings present:

Finally, the domain controller provision kicks in. Once done, the virtual machine gets rebooted and we execute another set of Pester tests to ensure that the domain controller was setup correctly.

Moreover, vagrant-uplift knows that Active Directory services don’t necessarily come up online and delay is needed. If you try to create new users or resolve existing, queries against AD fail. So we wait until services are up and running, and we can continue with initial user setup:

Well done! At this point, you have your domain controller done for you. Check out VirtualBox and use default vagrant user with vagrant password to get into and explore what’s in there.

No way, right?!

What’s next?

Congratulations! It was not easy, but you did it, and thank you very much for staying with us for a while.

We hope that this post provides a quick overview of what Vagrant can bring into your life. Automation can be easy and enjoyable, and we did our best to reduce the complexity of the infrastructure setup while building and open-sourcing the Uplift Project.

What’s next for us? — posts on domain join, SQL, SharePoint and CRM

What else can you do? Review this post example on Github:

You should already have an idea or two, but here are a few more scenarios to explore:

  • You can destroy and recreate the domain controller again!
vagrant destroy --force
vagrant up
  • You can add your own provision into Vagrantfile; create users, groups, build on top of the already existing domain controller

A few links to follow up:

If you like what we did, feel free to share feedback and improvements in the comments, follow us here or on Twitter and feel free to share this post too.

SubPointSolutions

Easy SharePoint automation for developers and engineers.

SubPointSupport

Written by

Easy SharePoint automation for developers and engineers. Provision SharePoint artifacts and deliver SharePoint infrastructure with confidence, sanity and joy.

SubPointSolutions

Easy SharePoint automation for developers and engineers.