Ansible WinRM: Configure Windows Remote Management Connection (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
How to configure WinRM for Ansible Windows automation. Set up WinRM HTTPS, authentication methods, pywinrm, troubleshoot connection errors.
Ansible + Windows: How It Works
Ansible manages Windows machines over WinRM (Windows Remote Management) instead of SSH. No agent is installed on Windows — Ansible sends PowerShell commands over WinRM and collects results.
┌──────────────┐ WinRM/HTTPS ┌──────────────┐
│ Control │ ──────────────────▶│ Windows │
│ Node │ (port 5986) │ Server │
│ (Linux) │ │ │
└──────────────┘ └──────────────┘
Ansible + pywinrm WinRM enabled
Requirements:
• Control node: Linux or macOS (Ansible doesn't run on Windows as control node)
• Managed nodes: Windows Server 2016+ or Windows 10+
• Python package: pywinrm
• WinRM enabled on Windows hosts
See also: AAP 2.6 Windows Automation: WinRM, PowerShell, and Active Directory Management
Enable WinRM on Windows
PowerShell Script (Recommended)
# Run as Administrator on each Windows host
# Download and run the Ansible WinRM setup script
$url = "https://raw.githubusercontent.com/ansible/ansible-documentation/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file
Manual Setup
# Enable WinRM
Enable-PSRemoting -Force
# Set up HTTPS listener (recommended for production)
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation Cert:\LocalMachine\My
winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=`"$env:COMPUTERNAME`";CertificateThumbprint=`"$($cert.Thumbprint)`"}"
# Allow basic auth (for testing only)
winrm set winrm/config/service/auth '@{Basic="true"}'
# Allow unencrypted (NEVER in production)
# winrm set winrm/config/service '@{AllowUnencrypted="true"}'
# Set execution policy
Set-ExecutionPolicy RemoteSigned -Force
# Configure firewall
New-NetFirewallRule -Name "WinRM-HTTPS" -DisplayName "WinRM over HTTPS" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5986 -Action Allow
Enable WinRM via Group Policy (Domain)
Computer Configuration → Administrative Templates → Windows Components → Windows Remote Management → WinRM Service
→ Allow remote server management through WinRM → Enabled
→ IPv4 filter: * (or specific subnets)
Inventory for Windows
# inventory/windows.yml
all:
children:
windows:
children:
web_servers:
hosts:
web-win-01:
ansible_host: 10.0.1.10
web-win-02:
ansible_host: 10.0.1.11
domain_controllers:
hosts:
dc-01:
ansible_host: 10.0.0.1
dc-02:
ansible_host: 10.0.0.2
sql_servers:
hosts:
sql-01:
ansible_host: 10.0.2.10
vars:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
ansible_port: 5986
ansible_winrm_scheme: https
ansible_user: "{{ vault_win_user }}"
ansible_password: "{{ vault_win_password }}"
Kerberos Authentication (Domain-Joined)
# ansible.cfg
[defaults]
# Kerberos requires: pip install pywinrm[kerberos]
# inventory vars:
# ansible_winrm_transport: kerberos
# ansible_user: ansible@COMPANY.COM
# ansible_password: vault_password
# Install Kerberos support
pip install pywinrm[kerberos]
# Configure /etc/krb5.conf
# [realms]
# COMPANY.COM = {
# kdc = dc-01.company.com
# admin_server = dc-01.company.com
# }
See also: Ansible Windows Server 2025 Automation: WinRM, PSRP, Active Directory, IIS, Hyper-V Complete Guide
Windows Features and Roles
---
- name: Configure Windows Server roles
hosts: web_servers
tasks:
- name: Install IIS
ansible.windows.win_feature:
name:
- Web-Server
- Web-Asp-Net45
- Web-Mgmt-Console
- Web-Scripting-Tools
state: present
include_management_tools: true
register: iis_install
- name: Reboot if required
ansible.windows.win_reboot:
reboot_timeout: 600
when: iis_install.reboot_required
- name: Install .NET Framework 4.8
ansible.windows.win_feature:
name: NET-Framework-45-Features
state: present
include_sub_features: true
- name: Remove unnecessary features
ansible.windows.win_feature:
name:
- Telnet-Client
- TFTP-Client
state: absent
IIS Web Server Management
---
- name: Configure IIS
hosts: web_servers
tasks:
- name: Create application pool
community.windows.win_iis_webapppool:
name: MyAppPool
state: started
attributes:
managedRuntimeVersion: v4.0
managedPipelineMode: Integrated
startMode: AlwaysRunning
processModel.identityType: ApplicationPoolIdentity
processModel.idleTimeout: "00:00:00"
recycling.periodicRestart.time: "00:00:00"
- name: Create website
community.windows.win_iis_website:
name: MyWebApp
state: started
port: 443
ssl: true
ip: "*"
hostname: app.company.com
physical_path: C:\inetpub\myapp
application_pool: MyAppPool
parameters: |
logFile.directory:C:\logs\iis
- name: Create virtual directory
community.windows.win_iis_virtualdirectory:
name: api
site: MyWebApp
physical_path: C:\inetpub\myapp\api
state: present
- name: Deploy application files
ansible.windows.win_copy:
src: app/
dest: C:\inetpub\myapp\
force: true
notify: restart iis app pool
handlers:
- name: restart iis app pool
community.windows.win_iis_webapppool:
name: MyAppPool
state: restarted
See also: Ansible for Windows Server Enterprise Management: Active Directory, IIS, and Group Policy
Software Installation
---
- name: Install software on Windows
hosts: windows
tasks:
# Chocolatey packages
- name: Install Chocolatey
chocolatey.chocolatey.win_chocolatey:
name: chocolatey
state: present
- name: Install common tools
chocolatey.chocolatey.win_chocolatey:
name: "{{ item }}"
state: present
loop:
- googlechrome
- 7zip
- notepadplusplus
- git
- vscode
- python3
# MSI packages
- name: Install application from MSI
ansible.windows.win_package:
path: https://download.company.com/app-2.0.msi
product_id: '{12345678-1234-1234-1234-123456789012}'
arguments: /quiet /norestart INSTALLDIR=C:\App
state: present
# EXE installers
- name: Install agent
ansible.windows.win_package:
path: C:\temp\agent-setup.exe
arguments: /S /v"/qn SERVERIP=10.0.0.100"
expected_return_code: [0, 3010]
state: present
Active Directory
ansible-galaxy collection install microsoft.ad
---
- name: Manage Active Directory
hosts: domain_controllers
tasks:
- name: Create OU structure
microsoft.ad.ou:
name: "{{ item.name }}"
path: "{{ item.path }}"
state: present
protected: true
loop:
- { name: "Company", path: "DC=company,DC=com" }
- { name: "Users", path: "OU=Company,DC=company,DC=com" }
- { name: "Groups", path: "OU=Company,DC=company,DC=com" }
- { name: "Servers", path: "OU=Company,DC=company,DC=com" }
- { name: "Workstations", path: "OU=Company,DC=company,DC=com" }
- name: Create AD users
microsoft.ad.user:
name: "{{ item.username }}"
firstname: "{{ item.first }}"
surname: "{{ item.last }}"
password: "{{ item.password }}"
state: present
path: "OU=Users,OU=Company,DC=company,DC=com"
email: "{{ item.username }}@company.com"
groups:
add:
- Domain Users
- "{{ item.department }}"
update_password: on_create
loop: "{{ ad_users }}"
no_log: true
- name: Create security groups
microsoft.ad.group:
name: "{{ item }}"
scope: global
category: security
path: "OU=Groups,OU=Company,DC=company,DC=com"
state: present
loop:
- IT-Admins
- Developers
- Finance
- HR
- name: Join computer to domain
microsoft.ad.membership:
dns_domain_name: company.com
domain_admin_user: "{{ vault_domain_admin }}"
domain_admin_password: "{{ vault_domain_password }}"
domain_ou_path: "OU=Servers,OU=Company,DC=company,DC=com"
state: domain
reboot: true
Windows Services
- name: Configure services
ansible.windows.win_service:
name: "{{ item.name }}"
start_mode: "{{ item.start_mode }}"
state: "{{ item.state }}"
loop:
- { name: wuauserv, start_mode: auto, state: started } # Windows Update
- { name: W3SVC, start_mode: auto, state: started } # IIS
- { name: Spooler, start_mode: disabled, state: stopped } # Print Spooler (security)
- { name: RemoteRegistry, start_mode: disabled, state: stopped }
- name: Create custom Windows service
ansible.windows.win_service:
name: MyAppService
path: C:\App\myapp.exe --service
display_name: "My Application Service"
description: "Custom application service"
start_mode: auto
state: started
username: .\svc_myapp
password: "{{ vault_svc_password }}"
dependencies:
- LanmanServer
- MSSQLSERVER
Registry Management
- name: Configure registry settings
ansible.windows.win_regedit:
path: "{{ item.path }}"
name: "{{ item.name }}"
data: "{{ item.data }}"
type: "{{ item.type }}"
loop:
# Disable SMBv1
- path: HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
name: SMB1
data: 0
type: dword
# Enable audit policy
- path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit
name: ProcessCreationIncludeCmdLine_Enabled
data: 1
type: dword
# Set RDP timeout
- path: HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
name: MaxIdleTime
data: 900000
type: dword
Windows Updates
---
- name: Patch Windows servers
hosts: windows
serial: 2 # Patch 2 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: "Installed {{ update_result.installed_update_count }} updates on {{ inventory_hostname }}"
when: update_result.installed_update_count > 0
PowerShell Execution
- name: Run PowerShell script
ansible.windows.win_powershell:
script: |
$services = Get-Service | Where-Object { $_.Status -eq 'Running' }
$services | Select-Object Name, DisplayName, StartType |
ConvertTo-Json
register: ps_result
- name: Run PowerShell with parameters
ansible.windows.win_powershell:
script: |
param($Path, $Days)
Get-ChildItem -Path $Path -Recurse |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$Days) } |
Remove-Item -Force
parameters:
Path: C:\Logs
Days: 30
Security Hardening
---
- name: Windows security hardening
hosts: windows
tasks:
- name: Set password policy
ansible.windows.win_security_policy:
section: System Access
key: "{{ item.key }}"
value: "{{ item.value }}"
loop:
- { key: MinimumPasswordLength, value: 14 }
- { key: PasswordComplexity, value: 1 }
- { key: MaximumPasswordAge, value: 90 }
- { key: LockoutBadCount, value: 5 }
- name: Disable unnecessary features
ansible.windows.win_feature:
name:
- Telnet-Client
- TFTP-Client
- SMB1Protocol
state: absent
- name: Configure Windows Firewall
community.windows.win_firewall_rule:
name: "Block Telnet Inbound"
localport: 23
protocol: tcp
direction: in
action: block
enabled: true
state: present
- name: Enable Windows Defender
ansible.windows.win_powershell:
script: |
Set-MpPreference -DisableRealtimeMonitoring $false
Set-MpPreference -MAPSReporting Advanced
Update-MpSignature
FAQ
Can Ansible run on Windows as a control node?
No. The Ansible control node must be Linux or macOS. You can manage Windows from Linux using WinRM. If you only have Windows, use WSL2 (Windows Subsystem for Linux) to run Ansible.
WinRM or SSH for Windows?
WinRM is the standard and best-supported connection method. Windows 10+ includes OpenSSH Server, and Ansible can use ansible_connection: ssh with it. However, WinRM provides better integration with Windows authentication (NTLM, Kerberos, CredSSP). Use WinRM unless you have specific SSH requirements.
How do I handle reboots?
Use ansible.windows.win_reboot after tasks that require reboot (Windows Updates, feature installation). Set appropriate reboot_timeout for long updates. Check reboot_required in task results to conditionally reboot.
What about Windows containers?
Ansible manages Windows containers with community.docker collection over WinRM. Docker Desktop or Docker EE on Windows Server works with the same docker_container module.
Conclusion
Ansible automates Windows at scale — IIS, Active Directory, Windows features, software deployment, security hardening, and patch management. Configure WinRM once, and you manage Windows the same way you manage Linux: declarative YAML playbooks, idempotent operations, version-controlled infrastructure. Use Kerberos for domain environments, Chocolatey for package management, and serial for safe rolling updates.
Related Articles
• Ansible vs Puppet vs Chef Comparison • Ansible for Cisco Network Automation • AAP 2.6 Architecture and Components • Install Ansible Complete Guide • Ansible Dynamic Inventory Complete GuideCategory: installation