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.ymlActive 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: trueManage 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 SilentlyContinueSee 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: restartedWindows 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: trueCertificate 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\MyBest 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_logfor credentials — Prevent passwords from appearing in output- Use
microsoft.adcollection — Modern AD modules replacing oldercommunity.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-credsspFAQ
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
Category: installation