Skip to main content

  • Increase Speed to Market
    Deliver quality quicker by optimising your delivery pipeline, removing bottlenecks, getting faster feedback from customers and iterating quickly.

  • Enhance Customer Experience
    Delight your customers in every digital interaction by optimising system quality and performance to provide a smooth, speedy and seamless user experience.

  • Maximise Your Investment
    Realise a positive ROI sooner and maximise your investment by focusing your energy on high-value features, reducing waste, and finding and fixing defects early.
  • The Wellington City Council (WCC) wanted to deliver quality outcomes without breaking the bank. Find out how Planit’s fast and flexible resources helped WCC achieve this goal.

this is a test Who We Are Landing Page

Banking like a start-up.
Capture your audience
Do your systems pass the grade?
Innovate with confidence.
Game day performance.

Using Packer and Terraform to Deploy a Windows Server 2016 AMI on AWS - Part I

By Bruce Dominguez | Consultant

INSIGHTS // Articles

7 Mar 2019


INSIGHTS // Articles


By Bruce Dominguez

7 Mar 2019

Automating a deployment of Windows Server 2016 on AWS should be easy, right? After all, deploying an Ubuntu Server with Packer and Terraform is as easy as typing “Packer Build” and “Terraform apply”!

Well, maybe not that easy, as I encountered a few challenges doing it myself. However, I learned several valuable lessons along the way that I think are worth sharing:

Using Packer and Terraform to Deploy a Windows Server 2016 AMI on AWS - Part I

Packer not connecting via SSH? Enter WINRM

When creating images with Packer, SSH is used by default to connect, communicate and build the host server.

Here is where I ran into my first problem when building my Windows server. I decided to switch to WINRM as the communication method, but it turns out that WINRM runs a lot slower.

In order for my instance to use WINRM for my install, I needed to pass a PowerShell script as a User Data file to run the configuration at boot time. The script I used can be found here.

If you are used to bootstrapping a server, then this shouldn’t be new to you. I updated my Packer JSON script with the changes to create the following snapshot:

“builders”: [{
“type”: “amazon-ebs”,
“source_ami_filter”: {
“filters”: {
“virtualization-type”: “hvm”,
“name”: “Windows_Server-2016-English-Full-Base-*”,
“root-device-type”: “ebs”
“owners”: [“amazon”],
“most_recent”: true
“instance_type”: “t2.micro”,
“communicator”: “winrm”,
“winrm_username”: “Administrator”,
“winrm_insecure”: true,
“winrm_use_ssl”: true,
Is Ansible being problematic? Enter Chocolatey

With my packer issues solved, next up was the Ansible scripts to configure the server. But Ansible had the same problem that it required WINRM to communicate to the host, which meant I would need to make several updates and configuration changes.

I decided to use Chocolatey to get Ansible working. It is a more Windows-friendly package manager, and works much like Linux Apt-get or yum to install applications on Windows using a simple Choco Install app.

This was simple to implement as part of my packer build by writing a PowerShell script to run the install, which is featured below or can be found on GitHub. Make sure that the global auto confirm is enabled:

# Install Chocolatey
iex ((New-Object System.Net.WebClient).DownloadString(‘'))
# Globally Auto confirm every action
choco feature enable -n allowGlobalConfirmation
# Install Python 2.x 2.7.15
choco install python2

Before installing any or all of the packages, something had to be done about Windows User Access Control (UAC). It will halt unattended application installs to ask for the admin password when an app is about to be installed on the server.

Running this quick PowerShell script prior to the Chocolatey installs will take care of UAC:

Write-Host “Disabling UAC…”
New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA -PropertyType DWord -Value 0 -Force
New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Policies\System -Name ConsentPromptBehaviorAdmin -PropertyType DWord -Value 0 -Force
So defining my PowerShell scripts in my Packer JSON script looks a little like this.
“provisioners”: [
“type”: “powershell”,
“scripts”: [

So defining my PowerShell scripts in my Packer JSON script looks a little like this.

“provisioners”: [
“type”: “powershell”,
“scripts”: [
RDP, why don’t you work after sysprep?!

At this point all of the packages should be installed on the server. Now it’s time to Sysprep the server to ensure it has a new computer Security Identifier (SID).

This can be done with two PowerShell commands for Windows Server 2016, which are already available on the server supplied by AWS. All that’s left to do is add inline PowerShell scripts to the existing script:

“type”: “powershell”,
“inline”: [
“C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule”,
“C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\SysprepInstance.ps1 -NoShutdown”

This command is then used to validate that everything is working correctly in the script:

Packer validate Windows.json
Template validated successfully

Typing “packer build windows.json” will create the new Windows Server 2016 Amazon Machine Image (AMI). Approximately 10 minutes later there should be a new AMI under the images section in the Elastic Compute Cloud (EC2) console of AWS.

All systems go?

In my case, I initially encountered some trouble with RDP failing to connect to my instance so I couldn’t boot it. After checking the Network Access Control Lists (NACLs) and Security Group settings, it turned out that the Sysprep had disabled the terminal services.

This was easily solved with this PowerShell script that runs as part of the user data on boot up. And with that, I now had a brand-new Windows AMI with all of my apps installed, and I am able to launch multiple instances and connect to them.

In part 2 of this article series, I will look at how to use Terraform to predictably deploy the new server in AWS. I will also show how to store key pairs on Amazon Simple Storage Service (S3) and automate the decryption of the Windows Admin password to easily connect them.

Join The Discussion
Enquire About Our Services