Packer: Building Win 2016 Vagrant Image

Building Windows 2016 Vagrant Box on macOS

Joaquín Menchaca (智裕)
4 min readJun 18, 2018

--

Recently, I wanted to play with Docker containers on the latest Windows Server, but I don’t have any Windows 2016 systems readily at my disposal. I would like to have the same sort of functionality I get with Vagrant and Linux systems, but because Windows operating system is strictly licensed, you cannot just pull it down off the Internet (at least legally), so you need to create your own image.

The tool that is popular for this activity is Packer from Hashicorp. This tool can build Virtualbox (optionally packaged up for use with Vagrant), Docker, or other virtual and cloud images. We concerned with creating Vagrant images for our purposes.

Packer is not an easy tool to use when starting out, at least with building virtual machine images from the install CDs. So instead of re-inventing the wheel, we can leverage from existing work out there, such as work done by Matt Wrock:

https://github.com/mwrock/packer-templates/

I came across his material from Learn Chef Rally, which pointed creating Windows 2012r2 images for testing with Chef, but this version of Windows won’t work for us because containers are only supported in Windows 2016.

This guide walks you through creating Windows 2016 virtualbox images for using Matt Wrock’s packer templates.

Getting Started

Before we jump straight into building this, we need to get the necessary tools, download the build scripts, and make some fixes to the source code.

Tools Required

For this project, we need to install the following tools: git, ChefDK, Packer, Virtualbox, and Vagrant.

On macOS (aka Mac OS X), you can use Homebrew to fetch these:

cat <<-BREWFILE > Brewfile
tap chef/chef
brew 'gnu-sed', args: ['with-default-names'] # GNU Sed
brew git
brew packer
cask chefdk
cask virtualbox
cask virtualbox-extension-pack
cask vagrant
BREWFILE
brew bundle --verbose

Source Repository

With git, we need to clone the repository somewhere:

mkdir $HOME/workarea
cd $HOME/workarea
git clone git@github.com:mwrock/packer-templates.git

Fetching the Install Media

I highly recommend fetching the install media from Microsoft and saving it locally, rather than downloading this each and every time you build this project.

ISO_ARTIFACT=14393.0.160715-1616.RS1_RELEASE_SERVER_EVAL_X64FRE_EN-US.ISO
URL_PREFIX="http://care.dlservice.microsoft.com"
URL_PATH="dl/download/1/6/F/16FA20E6-4662-482A-920B-1A45CF5AAE3C/"
ISO_URL="${URL_PREFIX}/${URL_PATH}/${ISO_ARTIFACT}"
curl -o ${HOME}/Downloads ${ISO_URL}

Fixing Some Issues

We’ll need to fix some issues before we attempt this.

cd $HOME/workarea/packer-templates
pushd cookbooks/packer-template
# Remove dependency to Windows cookbook
sed -i '/depends.*windows/d' metadata.rb # GNU Sed
rm Berksfile.lock
berks
berks vendor ../../vendor/cookbooks
popd

Some notes about what we are doing here.

The windows cookbook is no longer needed as most of the underlying resources have been fully integrated into Chef 14. The current version 4.3.2 is not compatible with Chef 14 and will break Chef if it is included. Thus we can remove the dependency for this cookbook.

The berks tool is used to update the dependencies, but first we need to remove the current lock file as it is obsolete and not compatible with Chef 14. Running berks will create a new updated lock file, and running berks vendor will download cookbooks into the vendored directory.

Building The Image

If you previously downloaded the artifact, you can run this command:

ISO_ARTIFACT=14393.0.160715-1616.RS1_RELEASE_SERVER_EVAL_X64FRE_EN-US.ISO
ISO_URL=${HOME}/Downloads/${ISO_ARTIFACT}"
packer build \
-var "iso_url=${ISO_URL}" \
-force -only virtualbox-iso \
vbox-2016.json

If you wanted to download the image and build in one command (the default), then simply do:

packer build \
-force -only virtualbox-iso \
vbox-2016.json

Manually Testing the Image

Add the Windows 2016 Box

Once the build is finished, we need to add the box to our vagrant environment. The build script (vbox-2016.json) will output a Vagrant box called windows2016min-virtualbox.box.

NAMESPACE=myboxen
BOXNAME=win2016
ARTIFACT=windows2016min-virtualbox.box
vagrant box add ${ARTIFACT} --name ${NAMESPACE}/${BOXNAME}

Test the Windows 2016 Box

Now that the Vagrant box is available to our environment, we can test it out using this:

NAMESPACE=myboxen
BOXNAME=win2016
cd
mkdir winbox-test && cd winbox-test
vagrant init ${NAMESPACE}/${BOXNAME}
vagrant up

You’ll need to have a remote desktop client installed. If you have Microsoft Remote Desktop (which is unfortunately only distributed through Apple Store), you can type this to remote into the system:

RDP_ADDR="full%20address=s:127.0.0.1:3389"
RDP_WIDTH="desktopwidth=i:1280"
RDP_HEIGHT="desktopheight=i:1024"
open "rdp://${RDP_ADDR}&${RDP_HEIGHT}&${RDP_WIDTH}"

When prompted, use vagrant for the username and password.

Segue: Remote Desktop Function

If you want an easy way to run rdp from the command line, defaulting to local host to access your Windows vagrant box, you can add this to your shell environment, e.g. .bashrc or .zshrc.

rdp() {
# default variables
RDP_ADDR=${1:-'127.0.0.1:3389'}
RDP_WIDTH=${2:-'1280'}
RDP_HEIGHT=${3:-'1024'}
# formatted strings to feed MS Remote Desktop client
RDP_ADDR="full%20address=s:${RDP_ADDR}"
RDP_WIDTH="desktopwidth=i:${RDP_WIDTH}"
RDP_HEIGHT="desktopheight=i:${RDP_HEIGHT}"
open "rdp://${RDP_ADDR}&${RDP_HEIGHT}&${RDP_WIDTH}"
}

Then you can just type rdp or the full command with other options:

rdp localhost:3389 1920 1080

Conclusion

And Voilà, you now have a usable and disposable Windows Server 2016 test environment.

--

--

Joaquín Menchaca (智裕)

DevOps/SRE/PlatformEng — k8s, o11y, vault, terraform, ansible