unit 8 · Windows track

Windows collections & modules

The win_ toolbox and where it lives

essential · 6 min · windows

you may want to read 4 · Collections & FQCN , 30 · Windows connections: WinRM, PSRP, SSH first — but nothing is locked

tl;dr

  • Windows modules live in ansible.windows (core) and community.windows (extended) — not ansible.builtin.
  • Your playbook habits transfer; module names don't — copy becomes ansible.windows.win_copy.
  • win_chocolatey is NOT in ansible.windows — it ships in the vendor collection chocolatey.chocolatey.

why it matters Point ansible.builtin.copy at a Windows host and the play dies — Windows automation runs on a separate module family spread across five collections, and you need that map before day one.

Lesson 4 planted the warning: Linux and Windows modules live in different collections. That isn’t packaging trivia. Everything in ansible.builtin is Python, executed by the Python interpreter on the managed node — and your Windows hosts don’t have one. Windows modules are PowerShell, executed by the PowerShell already on every box. Same playbook grammar, same FQCN discipline — a physically different toolbox. This lesson is the map.

Five collections cover the estate

  • ansible.windows — the core: files, services, packages, registry, users, commands. If a task feels like daily Windows admin, start here.
  • community.windows — the extended set: finer-grained Windows Update tooling, advanced firewall management, the long tail.
  • chocolatey.chocolatey — Chocolatey’s own vendor collection, home of win_chocolatey for package installs.
  • microsoft.iis — IIS management, published under Microsoft’s own namespace.
  • microsoft.ad — Active Directory: domain join, users, groups. The old win_domain_* modules were removed from ansible.windows in this collection’s favor.
ansible-galaxy collection install ansible.windows community.windows
one line, both workhorse collections

The modules you’ll actually use

Organized the way the work arrives, not alphabetically:

  • Packages & patching — win_package (MSI/EXE installers), win_updates (drive Windows Update), win_feature (server roles and features), win_get_url (download an installer), plus win_chocolatey from its vendor collection.
  • Services — win_service: your Set-Service + Start-Service muscle memory, declaratively.
  • Files, registry, users — win_copy, win_regedit, win_user.
  • Domain — microsoft.ad.membership joins or removes a machine from AD; older tutorials reach for win_domain_membership, which no longer exists in ansible.windows.
  • Escape hatches — win_shell runs PowerShell; win_command runs an executable directly. Same deal as their Linux cousins: always changed, never idempotent by default — lesson 22’s rules apply unchanged.

The promise from lesson 1, kept: win_dsc lets an Ansible task drive any existing PowerShell DSC resource, so prior DSC work gets reused rather than rewritten. The family in action, full FQCN as always:

- name: Install the IIS role # Install-WindowsFeature, declaratively
  ansible.windows.win_feature:
    name: Web-Server
    state: present

- name: Ensure IIS runs at boot # Set-Service + Start-Service in one
  ansible.windows.win_service:
    name: W3SVC
    state: started
    start_mode: auto
core modules from ansible.windows, FQCN as always

What transfers, what doesn’t

Be precise here, because it decides how much of lessons 8–29 you keep: all of it, except the module names. Inventory, group_vars, variables, when, loop, handlers, register, roles, Vault — identical on Windows. What does not transfer is any assumption that a win_ module is its Linux cousin renamed. ansible.builtin.copy becomes ansible.windows.win_copy, but the parameters differ too. There’s no mode: '0644': Windows permissions are ACLs, not mode bits, and separate modules manage them. Read the module docs instead of pattern-matching from Linux.

Facts diverge the same way. gather_facts still works — a PowerShell implementation of the setup module runs instead of the Python one — but it returns different keys and values than a Linux host. ansible_os_family reports Windows, which is what a mixed playbook’s when: conditions key on. Beyond that, dump the facts on a real Windows host (lesson 17’s technique) before reusing any fact name a Linux example taught you.

You now know which collections to install and which module names to reach for. What the modules don’t decide: how you run as someone else, and how you write a path without YAML eating your backslashes. That’s next lesson — where Windows playbooks actually break.

at work, this sounds like

“The Chocolatey tasks aren’t resolving — did anyone install chocolatey.chocolatey?”
win_chocolatey ships in Chocolatey’s own vendor collection, not ansible.windows — if that collection isn’t installed, the module name never resolves.

self-check — recall, not a test

  1. 1 Your Linux role uses ansible.builtin.copy and ansible.builtin.service. What changes to target Windows?

  2. 2 Which collections ship win_chocolatey and the advanced firewall modules?

  3. 3 What does win_dsc do, and why would a Windows team care?

lab (optional — never required)

Install ansible.windows and community.windows with ansible-galaxy, then run ansible.windows.win_ping and this lesson’s win_feature task against your Windows host.

needs: A Windows Server VM reachable over WinRM or SSH — the target you set up in lesson 32. No Windows VM, no lab.

next up 34 · become, runas & Windows paths 6 min · unit 8