AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible for Windows Server Enterprise Management: Active Directory, IIS, and Group Policy

By Luca Berton · Published 2024-01-01 · Category: installation

Manage Windows Server infrastructure with Ansible. Automate Active Directory, IIS, Group Policy, Windows Updates, and domain operations at enterprise scale.

Introduction

Enterprise environments run Windows Server alongside Linux — and both need automation. Ansible manages Windows through WinRM (Windows Remote Management) using PowerShell, with no agent installation required on target hosts. From Active Directory to IIS to Windows Updates, Ansible provides consistent automation across your entire hybrid infrastructure.

See also: AAP 2.6 Windows Automation: WinRM, PowerShell, and Active Directory Management

Windows Connection Setup

Enable WinRM on Windows Hosts

# Run on each Windows host (or via GPO)
# Download and run the ConfigureRemotingForAnsible.ps1 script
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy Bypass -File $file

# Or enable manually winrm quickconfig -q winrm set winrm/config/service '@{AllowUnencrypted="false"}' winrm set winrm/config/service/auth '@{Basic="true"}'

Ansible Inventory

# inventory/windows.yml
windows_servers:
  hosts:
    dc01.example.com:
    dc02.example.com:
    web01.example.com:
    web02.example.com:
    sql01.example.com:
  vars:
    ansible_connection: winrm
    ansible_winrm_transport: kerberos  # or ntlm, credssp
    ansible_winrm_server_cert_validation: ignore
    ansible_user: svc_ansible@EXAMPLE.COM
    ansible_password: "{{ vault_windows_password }}"

children: domain_controllers: hosts: dc01.example.com: dc02.example.com: web_servers: hosts: web01.example.com: web02.example.com: sql_servers: hosts: sql01.example.com:

Test Connectivity

ansible windows_servers -m ansible.windows.win_ping -i inventory/windows.yml

Active Directory Management

Create Organizational Units

- name: Manage Active Directory
  hosts: dc01.example.com
  tasks:
    - name: Create OUs
      microsoft.ad.ou:
        name: "{{ item.name }}"
        path: "{{ item.path }}"
        state: present
        protected: true
      loop:
        - { name: "Corporate", path: "DC=example,DC=com" }
        - { name: "Users", path: "OU=Corporate,DC=example,DC=com" }
        - { name: "Groups", path: "OU=Corporate,DC=example,DC=com" }
        - { name: "Servers", path: "OU=Corporate,DC=example,DC=com" }
        - { name: "Workstations", path: "OU=Corporate,DC=example,DC=com" }

Manage AD Users

    - name: Create AD users from CSV
      microsoft.ad.user:
        name: "{{ item.samaccountname }}"
        firstname: "{{ item.firstname }}"
        surname: "{{ item.lastname }}"
        email: "{{ item.email }}"
        upn: "{{ item.email }}"
        path: "OU=Users,OU=Corporate,DC=example,DC=com"
        password: "{{ item.initial_password }}"
        update_password: on_create
        state: present
        enabled: true
        groups:
          add:
            - "{{ item.department }}-Users"
      loop: "{{ lookup('file', 'users.csv') | community.general.from_csv }}"
      no_log: true

Manage AD Groups

    - name: Create security groups
      microsoft.ad.group:
        name: "{{ item.name }}"
        path: "OU=Groups,OU=Corporate,DC=example,DC=com"
        scope: global
        category: security
        state: present
        members:
          add: "{{ item.members }}"
      loop:
        - name: IT-Admins
          members: [admin1, admin2, admin3]
        - name: Developers
          members: [dev1, dev2, dev3, dev4]
        - name: HR-Staff
          members: [hr1, hr2]

Manage Group Policy Objects

    - name: Create and link GPOs
      ansible.windows.win_powershell:
        script: |
          Import-Module GroupPolicy

# Create GPO $gpo = New-GPO -Name "Security-Baseline" -ErrorAction SilentlyContinue if (-not $gpo) { $gpo = Get-GPO -Name "Security-Baseline" }

# Configure password policy Set-GPRegistryValue -Name "Security-Baseline" ` -Key "HKLM\Software\Policies\Microsoft\Windows\System" ` -ValueName "EnableSmartScreen" -Type DWord -Value 1

# Link to OU New-GPLink -Name "Security-Baseline" ` -Target "OU=Corporate,DC=example,DC=com" ` -ErrorAction SilentlyContinue

See also: Ansible Windows Server 2025 Automation: WinRM, PSRP, Active Directory, IIS, Hyper-V Complete Guide

IIS Web Server Management

Install and Configure IIS

- name: Configure IIS web servers
  hosts: web_servers
  tasks:
    - name: Install IIS with features
      ansible.windows.win_feature:
        name:
          - Web-Server
          - Web-Asp-Net45
          - Web-Http-Logging
          - Web-Security
          - Web-Mgmt-Console
          - Web-Mgmt-Service
        state: present

- name: Create application pool community.windows.win_iis_webapppool: name: MyApp state: started attributes: managedRuntimeVersion: v4.0 managedPipelineMode: Integrated startMode: AlwaysRunning processModel.idleTimeout: "00:00:00" processModel.identityType: SpecificUser processModel.userName: "EXAMPLE\\svc_myapp" processModel.password: "{{ vault_app_pool_password }}"

- name: Create website community.windows.win_iis_website: name: MyApp state: started port: 443 ssl: "MyApp-Cert" physical_path: C:\inetpub\myapp application_pool: MyApp parameters: "logfile.directory:C:\\logs\\iis"

- name: Deploy application ansible.windows.win_copy: src: builds/myapp-{{ version }}/ dest: C:\inetpub\myapp\ notify: restart app pool

- name: Bind SSL certificate ansible.windows.win_powershell: script: | $cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*myapp.example.com*" } | Sort-Object NotAfter -Descending | Select-Object -First 1 New-WebBinding -Name "MyApp" -Protocol "https" -Port 443 ` -HostHeader "myapp.example.com" -SslFlags 1 $binding = Get-WebBinding -Name "MyApp" -Protocol "https" $binding.AddSslCertificate($cert.Thumbprint, "My")

handlers: - name: restart app pool community.windows.win_iis_webapppool: name: MyApp state: restarted

Windows Updates

- name: Patch Windows servers
  hosts: windows_servers
  serial: "25%"  # Rolling update — 25% at a time
  tasks:
    - name: Install security updates
      ansible.windows.win_updates:
        category_names:
          - SecurityUpdates
          - CriticalUpdates
        state: installed
        reboot: true
        reboot_timeout: 1800
      register: update_result

- name: Report installed updates ansible.builtin.debug: msg: "{{ inventory_hostname }}: {{ update_result.installed_update_count }} updates installed"

See also: Ansible WinRM: Configure Windows Remote Management Connection (Complete Guide)

Windows Services and Firewall

    - name: Configure Windows services
      ansible.windows.win_service:
        name: "{{ item.name }}"
        start_mode: "{{ item.mode }}"
        state: "{{ item.state }}"
      loop:
        - { name: wuauserv, mode: auto, state: started }
        - { name: Spooler, mode: disabled, state: stopped }
        - { name: RemoteRegistry, mode: disabled, state: stopped }

- name: Configure Windows Firewall community.windows.win_firewall_rule: name: Allow HTTPS Inbound localport: 443 action: allow direction: in protocol: tcp state: present enabled: true

Certificate Management

    - name: Request certificate from CA
      ansible.windows.win_powershell:
        script: |
          $template = "WebServer"
          $subject = "CN=myapp.example.com"
          $san = "dns=myapp.example.com&dns=www.myapp.example.com"

$enrollment = New-Object -ComObject X509Enrollment.CX509Enrollment $request = New-Object -ComObject X509Enrollment.CX509CertificateRequestPkcs10

# Configure and submit certificate request Get-Certificate -Template $template ` -SubjectName $subject ` -DnsName "myapp.example.com","www.myapp.example.com" ` -CertStoreLocation Cert:\LocalMachine\My

Best Practices

Use Kerberos authentication — More secure than NTLM; required for domain operations Service accounts for Ansible — Dedicated AD service account with minimum required permissions WinRM over HTTPS — Always use HTTPS (port 5986) in production Rolling updates with serial — Patch servers in batches to maintain availability Test with --check — Dry-run Windows playbooks before applying no_log for credentials — Prevent passwords from appearing in output Use microsoft.ad collection — Modern AD modules replacing older community.windows.win_domain_* CredSSP for double-hop — When Ansible needs to access network resources through the Windows host

Required Collections

ansible-galaxy collection install ansible.windows
ansible-galaxy collection install community.windows
ansible-galaxy collection install microsoft.ad

# Python dependencies pip install pywinrm[kerberos] requests-credssp

FAQ

Can Ansible manage Windows without WinRM?

Yes — Ansible also supports SSH on Windows (OpenSSH server). But WinRM is the standard for enterprise Windows and supports more features.

Domain Controller management?

Use microsoft.ad collection for AD DS operations. Run against one DC; AD replication handles the rest.

How to handle reboots during patching?

win_updates with reboot: true handles reboot and reconnection automatically. Set reboot_timeout high enough for Windows Update reboots.

Conclusion

Ansible extends enterprise automation to Windows Server environments — managing Active Directory, IIS, Windows Updates, and security configurations through the same playbook-based approach used for Linux. Combined with AAP, it provides a single platform for hybrid infrastructure automation.

Related Articles

Ansible Automation Platform RBACAnsible Compliance AutomationAnsible Automation Platform 2.6

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home