unit 8 · Windows track

Setting up a Windows target

The script the docs disowned

essential · 7 min · windows

you may want to read 31 · The WinRM auth matrix first — but nothing is locked

tl;dr

  • Server 2016 / Windows 10 ship PowerShell 5.1 — no bootstrap needed on any current Windows target.
  • ConfigureRemotingForAnsible.ps1 lives on in tutorials, but official docs now warn against using it.
  • Modern setup: Enable-PSRemoting, explicit firewall rule, token filter policy, HTTPS listener, win_ping.

why it matters Every tutorial hands you the disowned bootstrap script; knowing the four explicit commands instead gives you a Windows setup you can defend line-by-line in a change request.

Lessons 30 and 31 were control-node work: pick a connection plugin, pick an auth row, set the variables in group_vars. The Windows box itself hasn’t been touched — and untouched, it turns you away. This lesson is the target side. You’ve enabled PowerShell remoting countless times; the honest summary is your usual move plus three explicit follow-ups.

First, what you don’t need. Windows modules execute as PowerShell on the target — no Python, no agent, nothing to install. The only floor is PowerShell 5.1 (which needs .NET Framework 4.6 or later), and Server 2016 and Windows 10 already ship it. On anything current, target prep is pure transport: get WinRM listening, reachable, and willing to log you in.

The script the docs disowned

Search “ansible windows setup” and most results — including tutorials written in 2026 — hand you one answer: download ConfigureRemotingForAnsible.ps1 and run it. For years it was the official on-ramp: one script enabling WinRM, creating listeners and opening the firewall in a lump. The official position has since flipped:

old — don't write this · discouraged — may be removed

ConfigureRemotingForAnsible.ps1 — the one-shot bootstrap script older official docs and most third-party guides still link. The docs now warn it “can cause several issues for the user” — and “Chances are it will be completely taken down in the future.” Recognise it in existing runbooks; don’t put it in new ones.

This split dates Windows guides the way bare module names dated Linux ones in lesson 4: a walkthrough built around the script predates the guidance change. The replacement is four moves you run — and can defend — individually.

The four moves

# 1. Enable the WinRM service and its HTTP listener — the move you know
Enable-PSRemoting -Force

# 2. Open 5985 yourself — no script deciding your firewall rules for you
New-NetFirewallRule -DisplayName "WinRM HTTP" -Direction Inbound `
  -LocalPort 5985 -Protocol TCP -Action Allow

# 3. Let remote local-admin logons keep their admin token (UAC filters it)
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System `
  -Name LocalAccountTokenFilterPolicy -Value 1 -Type DWord
HTTP transport: enable, open, un-filter

Enable-PSRemoting starts the service and creates the HTTP listener on 5985. The explicit firewall rule makes the network opening auditable instead of a side effect. Step 3 is the one that burns people: UAC’s remote token filtering strips administrative rights from network logons by local accounts. A perfectly valid local admin authenticates cleanly, then fails every privileged action. LocalAccountTokenFilterPolicy=1 disables that filtering. It exists to allow local accounts — if your inventory only uses domain accounts over Kerberos, skip it and keep the tighter default.

HTTP alone also pins you to the encrypting rows of lesson 31’s matrix. The fourth move adds TLS on 5986 so the rest of the matrix opens up:

# Self-signed cert, bound to an HTTPS listener, port opened
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME `
  -CertStoreLocation Cert:\LocalMachine\My
New-Item -Path WSMan:\localhost\Listener -Transport HTTPS -Address * `
  -CertificateThumbPrint $cert.Thumbprint -Force
New-NetFirewallRule -DisplayName "WinRM HTTPS" -Direction Inbound `
  -LocalPort 5986 -Protocol TCP -Action Allow
HTTPS transport on 5986 — demo-only, review before production

Prove it from the control node

Verification runs from the Linux side, as an ad-hoc command — the Windows analog of the ping you ran in lesson 7:

# not ICMP — a full WinRM login and PowerShell module round-trip
ansible windows -m ansible.windows.win_ping
the moment of truth

win_ping connects with your configured plugin, authenticates with your chosen matrix row, runs a trivial PowerShell module on the target and returns pong. Green output proves the entire 30–31–32 stack at once. Failure sorts by symptom. Connection refused points to this lesson’s listeners and firewall rules. A 401 points to lesson 31’s matrix. An instant error before any packet leaves points to a missing pywinrm extra on your own machine. Once pong comes back, the host is listening. Lesson 33 is what you can say to it: the win_* module catalog and the collections that ship it.

at work, this sounds like

“The old ConfigureRemoting script is still in that onboarding runbook.”
The Windows prep uses the discouraged bootstrap script — replace it with the explicit Enable-PSRemoting sequence before the script disappears.
“Local admins bounce off WinRM until you set the token filter policy.”
LocalAccountTokenFilterPolicy=1 is the registry switch that lets remote local-account logons keep their admin token.

self-check — recall, not a test

  1. 1 Why does current official guidance no longer point at ConfigureRemotingForAnsible.ps1?

  2. 2 A local admin account authenticates over WinRM but then hits access denied on everything, while RDP works fine. Which setup step was skipped?

  3. 3 What does a passing ansible.windows.win_ping actually prove?

lab (optional — never required)

Snapshot the VM, run the four-step setup by hand, then prove it end-to-end with ansible.windows.win_ping from your control node.

needs: A Windows Server 2016+ VM you can snapshot and break.

next up 33 · Windows collections & modules 6 min · unit 8