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 withserial — 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 RBAC • Ansible Compliance Automation • Ansible Automation Platform 2.6Category: installation