
How to Deploy a Windows Server VM Instance in GCP using Terraform
In this story, we will learn how to deploy a Windows Server VM Instance (VM) in GCP (Google Cloud Platform) using Terraform.
Prerequisite: GCP Credentials
Before creating our GCP VM Instances, we will need GCP Credentials to execute our Terraform code.
Please refer to the “How to Create a Service Account for Terraform in GCP (Google Cloud Platform)” story if you need help to create the credentials.
Note: Using private key .JSON files are great for learning and testing however they are not recommended in production environments. Never push private keys files to code repositories.
Creating a Terraform file for GCP Authentication
First, we create a file called “provider-variables.tf”, used by the GCP authentication variables, and add the following code to the file.
We will need a GCP Project Name, a GCP Region, and a .JSON file name with the private keys to authenticate to GCP.
# GCP authentication file
variable "gcp_auth_file" {
type = string
description = "GCP authentication file"
}# define GCP region
variable "gcp_region" {
type = string
description = "GCP region"
}# define GCP project name
variable "gcp_project" {
type = string
description = "GCP project name"
}Then we create the “provider-main.tf” file and add the following code:
The version in the “required_providers” / “google” section is useful to pin a specific version but is not required.
# Define Terraform provider
terraform {
required_version = "~> 1.0" required_providers {
google = {
source = "hashicorp/google"
version = "4.11.0" # pinning version
}
}
}# Define GCP provider
provider "google" {
credentials = file(var.gcp_auth_file)
project = var.gcp_project
region = var.gcp_region
zone = var.gcp_zone
}Finally, we use Provider in the “terraform.tfvars” file:
# GCP Settings
gcp_project = "kopicloud-medium"
gcp_region = "europe-west4"
gcp_auth_file = "../auth/kopicloud-medium.json"Creating a Terraform file for the Network
In this step, we will create the file “network-variables.tf” to configure network variables and add the following code:
variable "network-subnet-cidr" {
type = string
description = "The CIDR for the network subnet"
}Then, we create the “network-main.tf” file to configure the network and add the following code. This simple code will create a VPC and a public subnet.
# create VPC
resource "google_compute_network" "vpc" {
name = "kopicloud-vpc"
auto_create_subnetworks = "false"
routing_mode = "GLOBAL"
}# create public subnet
resource "google_compute_subnetwork" "network_subnet" {
name = "kopicloud-subnet"
ip_cidr_range = var.network-subnet-cidr
network = google_compute_network.vpc.name
region = var.gcp_region
}Creating a Terraform file for Network Firewall Rules
Now we will create the “network-firewall.tf” file used to create network firewall rules.
All traffic to VM instances in GCP, even from other instances, is blocked by the firewall unless firewall rules are created to allow it.
We will use the “target_tags” to apply firewall rules to VM instances. If no “target_tags” are specified, the firewall rule applies to all instances on the specified VPC network.
# Allow http
resource "google_compute_firewall" "allow-http" {
name = "kopicloud-fw-allow-http"
network = google_compute_network.vpc.name
allow {
protocol = "tcp"
ports = ["80"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["http"]
}# allow rdp
resource "google_compute_firewall" "allow-rdp" {
name = "kopicloud-fw-allow-rdp"
network = google_compute_network.vpc.name
allow {
protocol = "tcp"
ports = ["3389"]
} source_ranges = ["0.0.0.0/0"]
target_tags = ["rdp"]
}Creating a Terraform file for Windows Server Versions Variables
We will create the “windows-versions.tf” file, used to store variables for the different versions of Windows Server.
variable "windows_2012_r2_sku" {
type = string
description = "SKU for Windows Server 2012 R2"
default = "windows-cloud/windows-2012-r2"
}variable "windows_2016_sku" {
type = string
description = "SKU for Windows Server 2016"
default = "windows-cloud/windows-2016"
}variable "windows_2019_sku" {
type = string
description = "SKU for Windows Server 2019"
default = "windows-cloud/windows-2019"
}variable "windows_2022_sku" {
type = string
description = "SKU for Windows Server 2022"
default = "windows-cloud/windows-2022"
}Creating a Terraform file for the Windows Server VM Variables
Now we will create the “windows-vm-variables.tf” file, used to store variables for the Windows Server operating system.
variable "windows_instance_type" {
type = string
description = "VM instance type for Windows Server"
default = "n2-standard-2"
}Creating a Terraform file for the Windows Server VM Main File
Finally, create the “windows-vm-main.tf” file to build the GCP VM Instance. We will split the code for better clarity.
We will use a simple PowerShell script to bootstrap the VM instance. Next, the script will install IIS (Internet Information Server) on the server. This extra step is useful to make sure the server is working properly.
Note: this step is optional. If we don’t want to deploy IIS, we will need to remove the “metadata” section from the “windows-vm-main.tf” file and the http rule from tags.
For Windows Server, we can use different options to bootstrap VM instances.
- sysprep-specialize-script-ps1 = PowerShell script during the initial boot
- sysprep-specialize-script-cmd = Command Shell script during the initial boot
- windows-startup-script-ps1 = PowerShell script during each boot after the initial boot
- windows-startup-script-cmd = Command Shell script during each boot after the initial boot
We can use multiple startup scripts.
data "template_file" "windows-metadata" {
template = <<EOF
# Install IIS
Install-WindowsFeature -name Web-Server -IncludeManagementTools;
EOF
}This section of code will create the VM Instance. To update the version of Windows Server, update the image line with a variable from the “windows-versions.tf” file.
resource "google_compute_instance" "vm_instance_public" {
name = "kopicloud-vm"
machine_type = var.windows_instance_type
zone = var.gcp_zone
hostname = "kopicloud-vm.kopicloud.com"
tags = ["rdp","http"] boot_disk {
initialize_params {
image = var.windows_2022_sku
}
} metadata = {
sysprep-specialize-script-ps1 = data.template_file.windows-metadata.rendered
} network_interface {
network = google_compute_network.vpc.name
subnetwork = google_compute_subnetwork.network_subnet.name
access_config { }
}
}How to Find Windows Server VM SKUs for Terraform
We open the “gcloud CLI” tool or the “Cloud Shell” in the GCP Console and type:
gcloud compute images list --filter 'family ~ windows'and we will get the list of Windows Server images available. The “PROJECT” and “FAMILY” columns are the two we need to combine to create the image name.
NAME: windows-server-2012-r2-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2012-r2-core
DEPRECATED:
STATUS: READYNAME: windows-server-2012-r2-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2012-r2
DEPRECATED:
STATUS: READYNAME: windows-server-2016-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2016-core
DEPRECATED:
STATUS: READYNAME: windows-server-2016-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2016
DEPRECATED:
STATUS: READYNAME: windows-server-2019-dc-core-for-containers-v20220211
PROJECT: windows-cloud
FAMILY: windows-2019-core-for-containers
DEPRECATED:
STATUS: READYNAME: windows-server-2019-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-2019-core
DEPRECATED:
STATUS: READYNAME: windows-server-2019-dc-for-containers-v20220211
PROJECT: windows-cloud
FAMILY: windows-2019-for-containers
DEPRECATED:
STATUS: READYNAME: windows-server-2019-dc-v20220210
PROJECT: windows-cloud
FAMILY: windows-2019
DEPRECATED:
STATUS: READYNAME: windows-server-2022-dc-core-v20220215
PROJECT: windows-cloud
FAMILY: windows-2022-core
DEPRECATED:
STATUS: READYNAME: windows-server-2022-dc-v20220215
PROJECT: windows-cloud
FAMILY: windows-2022
DEPRECATED:
STATUS: READYNAME: windows-server-20h2-dc-core-v20220210
PROJECT: windows-cloud
FAMILY: windows-20h2-core
DEPRECATED:
STATUS: READYCreating the Input Definition Variables File
In the last step, we are going to create input definition variables file “terraform.tfvars” and add the following code to the file:
# Application Definition
company = "kopicloud"
app_name = "iac-windows"
app_domain = "kopicloud.com"
environment = "dev" # Dev, Test, Prod, etc# GCP Settings
gcp_project = "kopicloud-medium"
gcp_region = "europe-west4"
gcp_zone = "europe-west4-b"
gcp_auth_file = "../auth/kopicloud-medium.json"# GCP Netwok
network-subnet-cidr = "10.10.15.0/24"# Windows VM
windows_instance_type = "n2-standard-2"Windows Servers VM are NOT Allowed in Free Trials
Unfortunately, GCP is the only cloud provider that doesn’t support deploying Windows VM on the Free Trial, so if you try to run this code, you will get the following error:
Error: Error creating instance: googleapi: Error 400: Windows VM instances are not included with the free trial. To use them, first enable billing on your account. You’ll still be able to apply your free trial credits to eligible products and services., windowsVmNotAllowedInFreeTrialProject
The solution is to enable the Billing Account in our GCP Account.
The full code is available at https://github.com/KopiCloud/terraform-gcp-windows-vm
And that’s all, folks. If you liked this story, please show your support by 👏 this story. Thank you for reading!




