unit 8 · Windows track
Setting up a Windows target
The script the docs disowned
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:
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 DWordEnable-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 AllowProve 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_pingwin_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 Why does current official guidance no longer point at ConfigureRemotingForAnsible.ps1?
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 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.