Debugging a Windows BOSH VM and its firewall rules

I have been investigating using BOSH with Windows stemcells to help Windows developers have all the delights of BOSH for their deployment lifecycle.

Very quickly in the journey I created bugs that needed debugging, and it wasn’t the same debugging experience for a BOSH/Linux deployment. I got help. Hopefully the debugging tips below are helpful to you when you’ve got an .exe that needs to run on Windows and you want to use BOSH to do it.

Summary documentation for BOSH on Windows is available which was helpful.

The screen images in this blog post are from Windows Server 2012R2 stemcells which I found at

To experiment with BOSH on Windows I created a sample BOSH release which borrowed heavily from

It compiles a Hello World Golang web server that runs on port 3000. But it timed out when I tried to access the app:

$ curl -v
* Rebuilt URL to:
* Hostname was NOT found in DNS cache
*   Trying
* connect to port 3000 failed: Connection timed out
* Failed to connect to port 3000: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to port 3000: Connection timed out

This was deployed on Google Compute Platform (GCP) and I knew my GCP firewalls allowed any app on the bosh-bastion to access any VM in the subnet, including my Windows VM running at

Debugging time.

Fetching BOSH job logs

At the time of this writing, bosh2 logs --follow does not work on Windows VMs to stream the logs of running jobs, however, we still have the static dump version of bosh2 logs:

$ bosh2 logs -d simple-go-web-app
22:40:34 | Fetching logs for webapp/b95a2a12-b7c4-4c46-9003-713d64c013c0 (0): Finding and packing log files (00:00:01)
Downloading resource 'b174c5b7-da7c-40aa-5926-2af98a6332b2' to '/home/drnic/workspace/sample-go-windows-boshrelease/simple-go-web-app-20170723-224036-02661666.tgz'...

To unpack and view all the logs:

$ tar xfz simple-go-web-app-*; tail -n 200 simple-go-web-app/simple-go-web-app/* simple-go-web-app/*
==> simple-go-web-app/simple-go-web-app/job-service-wrapper.out.log <==
[martini] listening on :3000 (development)

It seems that the simple-go-web-app.exe compiled Golang app is successfully running and listening on port 3000.

Delete the logs:

rm -rf simple-go-web-app*

A one-line combo I used was:

bosh2 logs -d simple-go-web-app && tar xfz simple-go-web-app-* && tail -n 200 simple-go-web-app/simple-go-web-app/* simple-go-web-app/* | less && rm -rf simple-go-web-app*

These logs showed that the simple-go-web-app.exe was running and it thought it was listening on 3000.

Using RDP to access a Windows VM

Normally to access a BOSH VM we would use bosh2 ssh to get a secure terminal. This does not work with Windows servers. Instead, we must use the Microsoft Remote Desktop Protocol (RDP) [download links].

Currently RDP access and authentication is managed by the cloud provider, not via BOSH.

With luck, you can find the VM on GCP dashboard and click "RDP" button:


I wasn’t lucky.

Using RDP via an SSH tunnel

No matter how many firewalls or gateways or RDP clients I played with I could not get RDP working.

My eternal thanks go to David Jahn who suggested running an SSH tunnel from my local machine to the Windows VM thru the bastion.

To setup an SSH/RDP tunnel with GCP, where is the GCP IP of the VM to be debugged:

gcloud compute ssh bosh-bastion -- -L 3389:

This will open a normal ssh session into bosh-bastion but will transparently include a tunnel from localhost:3389 to

Using Microsoft Remote Desktop, create a new "desktop":


The username and password will change for each VM. The localhost:3389 will be available whenever you the gcloud compute ssh bosh-bastion -- -L ... command above is running.

To setup a username and password on the Windows VM, click "Set Windows password" and follow the prompts.


Initial look at how BOSH runs on Windows

As a quick sanity test, I confirmed that files and paths were as I expected.

In a PowerShell terminal, run:

cmd /c start /b set

The Path env var were displayed in full:

GooGet;C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\bin;C:\Program Files\Google\Compute Engine\metadata_scri
pts;C:\Program Files\Google\Compute Engine\sysprep;C:\var\vcap\bosh\bin

The BOSH packages were accessible via the normal folder aliases, within the c:\ drive:

C:\Users\drnicwilliams>dir c:\var\vcap\packages
    Directory: C:\var\vcap\packages
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d----l        7/23/2017   9:38 PM                simple-go-web-app

Firewalls were enabled by default

Using Internet Explorer, after disabling IE default security, I could view the http://localhost:3000 application locally:


This confirmed that the application was running as expected and can be accessed locally.

Therefore the Windows Server must have additional firewall rules that aren’t managed by GCP or BOSH that are blocking ingress traffic to port 3000.

To test, I disabled the private firewalls:


Success. The curl request from bosh-bastion now worked:

$ curl
Hello world

Configuring Windows Firewall from BOSH

Manually changing the firewall rules only demonstrated where the issue was. The BOSH release needed a specific firewall rule to allow TCP traffic into port 3000 (or whatever port the application is bound to) every time the release was deployed.

Windows Firewalls can be scripted using PowerShell New-NetFirewallRule command. To run PowerShell using BOSH, one option is to include a bin/pre-start.ps1 script.

New-NetFirewallRule -LocalPort <%= p("port") %> `
  -Protocol TCP `
  -Direction Inbound `
  -Name simple-go-web-app `
  -DisplayName simple-go-web-app

See pre-start.ps1 in the final BOSH job.

Other PowerShell hooks are documented


When deploying Windows Server VMs with BOSH we do lose a couple of standard debugging options we have with traditional BOSH Linux VMs. Instead we can use Microsoft RDP to get a Windows desktop session, as well as download the BOSH job logs using bosh2 logs.

The Windows stemcell has default firewall rules. If your BOSH jobs require additional ingress or egress rules, use a pre-start.ps1 script to run PowerShell commands.

Spread the word

twitter icon facebook icon linkedin icon