Deploying Windows EC2 instance using Terraform

Posted: January 8, 2018 in Amazon Web Services (AWS), AWS, Linux, terraform

In one of previous posts we deployed Linux Amazon instance using Terraform, now we’ll deploy Windows Server. Unlike previous approach, now we’ll store AWS Access Keys in separate file.

I created terraform.tfvars and stored keys there

AWS_ACCESS_KEY="some key"
AWS_SECRET_KEY="some keys"

There i also put Windows Server password

File contains variable and AMIs

variable "AWS_ACCESS_KEY" {}
variable "AWS_SECRET_KEY" {}
variable "AWS_REGION" { 
default = "eu-west-1" 
variable "WIN_AMIS" {
type = "map" default = { 
us-east-1 = "ami-30540427"
us-west-2 = "ami-9f5efbff"
eu-west-1 = "ami-cddc5bb4" 
variable "PATH_TO_PRIVATE_KEY" { default = "mykey" } 
variable "PATH_TO_PUBLIC_KEY" { default = "" 
variable "INSTANCE_USERNAME" { default = "admin" } 
variable "INSTANCE_PASSWORD" { }

In order to find out Window server AMI in AWS console go to EC2-Launch instance-Community AMIs, in search box type Windows, scroll until you find desired image and locate AMI-put that value into


in i put reference to terraform.tfvars

provider "aws" { 
access_key = "${var.AWS_ACCESS_KEY}"
secret_key = "${var.AWS_SECRET_KEY}"
region = "${var.AWS_REGION}" }

In is code for deploying Windows server:


It will create key pair, set AMI, and WinRM, copy local file to new instance and create security group and add EC2 instance to it




resource “aws_key_pair” “mykey” {
key_name = “mykey”
public_key = “${file(“${var.PATH_TO_PUBLIC_KEY}”)}”

resource “aws_instance” “win-example” {
ami = “${lookup(var.WIN_AMIS, var.AWS_REGION)}”
instance_type = “t2.micro”
key_name = “${aws_key_pair.mykey.key_name}”
user_data = <<EOF
net user ${var.INSTANCE_USERNAME} ‘${var.INSTANCE_PASSWORD}’ /add /y
net localgroup administrators ${var.INSTANCE_USERNAME} /add

winrm quickconfig -q
winrm set winrm/config/winrs ‘@{MaxMemoryPerShellMB=”300″}’
winrm set winrm/config ‘@{MaxTimeoutms=”1800000″}’
winrm set winrm/config/service ‘@{AllowUnencrypted=”true”}’
winrm set winrm/config/service/auth ‘@{Basic=”true”}’

netsh advfirewall firewall add rule name=”WinRM 5985″ protocol=TCP dir=in localport=5985 action=allow
netsh advfirewall firewall add rule name=”WinRM 5986″ protocol=TCP dir=in localport=5986 action=allow

net stop winrm
sc.exe config winrm start=auto
net start winrm

provisioner “file” {
source = “test.txt”
destination = “C:/test.txt”
connection {
type = “winrm”
timeout = “10m”
user = “${var.INSTANCE_USERNAME}”
password = “${var.INSTANCE_PASSWORD}”


output “ip” {




File contain security group definition, i just allowed traffic to all ports from anywhere (not a good security practice)

resource "aws_security_group" "allow-all" {
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [""]
ingress {
from_port = 0
to_port = 6556
protocol = "tcp"
cidr_blocks = [""]
tags {
Name = "allow-RDP"

Create key pair:

ssh-keygen -f mykey

Now test for errors and apply configuration :

 terraform init && terraform plan && terraform apply



  1. santhosh kumar says:

    hi i follwed this code as it is but i could not spin up up an instance please guide me how to connect to this instance also

    Liked by 1 person

  2. Kent says:

    Error: Unknown root level key: user_data

    Liked by 1 person

  3. Luk says:

    It does not work for me, well at least not completely. Still creating… (9m30s elapsed) Still creating… (9m40s elapsed) Still creating… (9m50s elapsed) Still creating… (10m0s elapsed) Still creating… (10m10s elapsed) Still creating… (10m20s elapsed)

    Error: Error applying plan:

    1 error(s) occurred:

    * timeout – last error: unknown error Post dial tcp i/o timeout

    It deploys win server though. When I log in using aws console I see that win instance is there but not configured because of that error.
    The only difference in my code is region “us-west-2” and of course ami “ami-c9deafb1” (win 2k16 server)
    Any advice?

    Liked by 1 person

  4. Kraemer says:

    i think it is nice but i search , how to join to a windows domain with Terraform.
    Have anybody an idea?


  5. Anish says:

    Error: Error applying plan:

    1 error(s) occurred:

    * 1 error(s) occurred:

    * unknown error Post dial tcp i/o timeout

    Terraform does not automatically rollback in the face of errors.
    Instead, your Terraform state file has been partially updated with
    any resources that successfully completed. Please address the error
    above and apply again to incrementally change your infrastructure.

    Any help is greatly appreciated


  6. JC says:
    type = “map” default = {
    (was throwing an error, changed default ={ to be on a separate line)
    tags {
    (throwing an error, changed to tags = {)


  7. RS says:

    I am trying to get the password of the ec2 instance once it is launched like the way you have described. How can I get it ? I am trying to do this command
    `aws ec2 get-password-data –instance-id “id” –priv-launch-key ~/Downloads/.pem` How can I provide the .pem file for authorization?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s