This guide provides a step-by-step guide for building a Windows 10 Pro / Enterprise Amazon Machine Image (AMI) using HyperV. The guide includes instructions for building a VHDX file using HyperV, converting the VHDX to an AMI, and creating a new EC2 instance using the AMI.
Building a VHDX file using HyperV
- Download Windows 10 Pro / Enterprise ISO
- Windows 10 Enterprise can be obtained with a free 90 day trial
- Install Windows 10 in Hyper-V
- Open Hyper-V Manager
- New → Virtual Machine
- Give it a name that makes sense for you (Windows 10 Golden, etc)
- Choose Generation 1
- UNCHECK “Use Dynamic Memory for this virtual machine” and give at least 2GB of memory.
- Choose you connection, Default Switch is fine unless you have specific requirements
- Choose where you want your virtual hard disk to live. Usually the default is fine.
- Select “Install an operating system from a bootable CD/DVD-ROM” and select the Image file (.iso) to your Windows 10 iso from the first step.
- Click Finish to create your machine
- Start and connect to your Virtual Machine
- Go through the normal windows setup process.
- Enable Remote Desktop
- Install the EC2 agent service
- (Optional) Some instance types require a driver to be installed for networking if it uses ENA
- (Optional) Install the GPU Drivers for the GPU of the instance type you are targeting. This is not necessary for non-GPU instances.
- At this point, Windows will have likely created an Automatic Checkpoint which we don’t want. Checkpoints create AVHDX files instead of the VHDX file we want containing the whole file system.
- Stop the running Virtual Machine
- Right click in the Checkpoints view on the “Automatic Checkpoint” and select “Delete Checkpoint”.
- Go in to the settings for your Virtual Machine and then Checkpoints
- Disable Checkpoints
- Start and then stop the running Virtual Machine to make sure it was merged
Converting VHDX to an AMI
- Install and setup the aws cli
- Optionally you can do the steps below manually through the AWS Console
- Create an S3 bucket, replacing
!!REPLACEME!!
with a unique bucket name aws s3 mb s3://!!REPLACEME_BUCKETNAME!! -region us-west-2
- Upload your VHDX file to the S3 bucket, replacing
!!REPLACEME!!
with the bucket name from above:
cd myvmfolder aws s3 cp codexaws.vhd s3://!!REPLACEME!! --region us-west-2
- Create a trust policy
- Place this file somewhere as
trust-policy.json
aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "vmie.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals":{ "sts:Externalid": "vmimport" } } } ] }
- Add policy to the
vmimport
role that was created in the last step - Create a file named
role-policy.json
and replace!!REPLACEME!!
with your S3 bucket name aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation" ], "Resource": [ "arn:aws:s3:::!!REPLACEME!!" ] }, { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::!!REPLACEME!!/*" ] }, { "Effect": "Allow", "Action":[ "ec2:ModifySnapshotAttribute", "ec2:CopySnapshot", "ec2:RegisterImage", "ec2:Describe*" ], "Resource": "*" } ]
- Create the image-builder configuration file
containers.json
with the following. Make sure to replace!!REPLACEME!!
with your bucket name and!!YOURVHDXFILENAME!!
with your .vhdx file name in S3:[{ "Description": "Windows 10 Base Install", "Format": "vhd", "UserBucket": { "S3Bucket": "!!REPLACEME!!", "S3Key": "!!YOURVHDXFILENAME!!" } }]
- Create the AMI:
aws ec2 import-image --description "Windows 10" --disk-containers file://containers.json --region us-west-2
- Watch the process with
watch aws ec2 describe-import-image-tasks --region us-west-2
- Once the process is finished, you can create a new EC2 instance using your new Windows 10 AMI. Make sure that you have installed the ENA if you want to use instance types that use the ENA, which is many of them. If you want to run on a GPU instance, then make sure that you have installed the correct GPU drivers.
Thank you to peterforgacs for posting this very useful gist which much of this guide is based off of