Introduction
Ansible connects to Windows hosts via WinRM (Windows Remote Management) or PSRP (PowerShell Remoting Protocol). This guide covers WinRM setup, HTTPS configuration, authentication options, and troubleshooting.
Quick Setup (PowerShell Script)
Run on each Windows host as Administrator:
# Download and run Ansible's 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
This script:
- Enables WinRM
- Creates a self-signed HTTPS certificate
- Opens firewall ports
- Enables basic authentication
Manual Setup
Step 1: Enable WinRM
# Enable WinRM service
Enable-PSRemoting -Force
# Set WinRM service to auto-start
Set-Service WinRM -StartupType Automatic
Start-Service WinRM
# Verify
winrm quickconfig
Step 2: Configure WinRM
# Allow unencrypted (HTTP) — only for testing
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
# Enable basic auth
winrm set winrm/config/service/auth '@{Basic="true"}'
# Increase memory per shell (critical for large tasks)
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'
# Increase max envelope size
winrm set winrm/config '@{MaxEnvelopeSizekb="500"}'
# Set max concurrent operations
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="50"}'
Step 3: HTTPS (Production)
# Create self-signed certificate
$cert = New-SelfSignedCertificate -DnsName "$env:COMPUTERNAME" -CertStoreLocation Cert:\LocalMachine\My
# Create HTTPS listener
winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=`"$env:COMPUTERNAME`";CertificateThumbprint=`"$($cert.Thumbprint)`"}"
# Verify listeners
winrm enumerate winrm/config/listener
Step 4: Firewall
# Allow WinRM HTTPS (5986)
New-NetFirewallRule -Name "WinRM-HTTPS" -DisplayName "WinRM HTTPS" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5986 -Action Allow
# Allow WinRM HTTP (5985) — only if needed
New-NetFirewallRule -Name "WinRM-HTTP" -DisplayName "WinRM HTTP" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5985 -Action Allow
Step 5: LocalAccountTokenFilterPolicy
Required for local admin accounts:
# Enable LocalAccountTokenFilterPolicy
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "LocalAccountTokenFilterPolicy" -Value 1 -Type DWord
Ansible Inventory Configuration
Basic HTTP (Testing Only)
[windows]
win-01 ansible_host=192.168.1.100
[windows:vars]
ansible_user=Administrator
ansible_password=SecurePassword123!
ansible_connection=winrm
ansible_port=5985
ansible_winrm_transport=basic
ansible_winrm_scheme=http
HTTPS (Production)
[windows:vars]
ansible_user=Administrator
ansible_password={{ vault_win_password }}
ansible_connection=winrm
ansible_port=5986
ansible_winrm_transport=ntlm
ansible_winrm_scheme=https
ansible_winrm_server_cert_validation=ignore
YAML Inventory
all:
children:
windows:
hosts:
win-01:
ansible_host: 192.168.1.100
vars:
ansible_user: Administrator
ansible_password: "{{ vault_win_password }}"
ansible_connection: winrm
ansible_port: 5986
ansible_winrm_transport: ntlm
ansible_winrm_scheme: https
ansible_winrm_server_cert_validation: ignore
Authentication Methods
| Transport | Description | Use Case |
|---|---|---|
basic | Username + password (HTTP) | Testing only |
ntlm | Windows NTLM | Local accounts |
kerberos | Kerberos/AD | Domain environments |
credssp | CredSSP | Double-hop scenarios |
certificate | Client certificate | Passwordless |
Kerberos (Active Directory)
# Install on controller
pip install pywinrm[kerberos]
sudo apt install krb5-user # Debian/Ubuntu
# Configure /etc/krb5.conf
[realms]
EXAMPLE.COM = {
kdc = dc01.example.com
admin_server = dc01.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
[windows:vars]
ansible_user=admin@EXAMPLE.COM
ansible_password={{ vault_password }}
ansible_connection=winrm
ansible_winrm_transport=kerberos
ansible_port=5986
CredSSP
pip install pywinrm[credssp]
ansible_winrm_transport=credssp
PSRP — Alternative to WinRM
PSRP (PowerShell Remoting Protocol) is faster and more reliable:
pip install pypsrp
[windows:vars]
ansible_connection=psrp
ansible_psrp_auth=ntlm
ansible_psrp_cert_validation=ignore
PSRP vs WinRM
| Feature | WinRM | PSRP |
|---|---|---|
| Speed | Good | Better |
| Reliability | Good | Better |
| Compatibility | All Windows | Windows 2012+ |
| Large outputs | Can fail | Handles well |
| Setup | Standard | Same as WinRM |
Test Connection
# Test with win_ping
ansible windows -m win_ping
# Verbose output
ansible windows -m win_ping -vvvv
# Ad-hoc command
ansible windows -m win_command -a "hostname"
Automate WinRM Setup with Ansible
For new Windows hosts that already have basic WinRM:
---
- name: Configure WinRM for Ansible
hosts: windows
tasks:
- name: Set MaxMemoryPerShellMB
ansible.windows.win_shell: |
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'
- name: Set MaxEnvelopeSizekb
ansible.windows.win_shell: |
winrm set winrm/config '@{MaxEnvelopeSizekb="500"}'
- name: Enable LocalAccountTokenFilterPolicy
ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
name: LocalAccountTokenFilterPolicy
data: 1
type: dword
- name: Ensure WinRM HTTPS firewall rule
community.windows.win_firewall_rule:
name: "WinRM HTTPS"
localport: 5986
action: allow
direction: in
protocol: tcp
state: present
enabled: true
Troubleshooting
"Connection refused" / "Connection timeout"
# Check WinRM is running
Get-Service WinRM
# Check listeners
winrm enumerate winrm/config/listener
# Check firewall
Get-NetFirewallRule | Where-Object { $_.DisplayName -like "*WinRM*" }
# Test from controller
Test-NetConnection -ComputerName 192.168.1.100 -Port 5986
"401 Unauthorized"
# Check auth settings
winrm get winrm/config/service/auth
# Verify LocalAccountTokenFilterPolicy
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "LocalAccountTokenFilterPolicy"
"MaxMemoryPerShellMB" errors
# Increase memory limit
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="2048"}'
"Network connection type is set to Public"
# Change network profile to Private
Set-NetConnectionProfile -InterfaceAlias "Ethernet" -NetworkCategory Private
# Then enable WinRM
Enable-PSRemoting -Force
Certificate Errors
# Ignore self-signed cert validation
ansible_winrm_server_cert_validation=ignore
Timeout Issues
# Increase timeouts
ansible_winrm_operation_timeout_sec=60
ansible_winrm_read_timeout_sec=70
Related Articles
Conclusion
For production: use HTTPS (port 5986) with NTLM or Kerberos authentication. Run the ConfigureRemotingForAnsible.ps1 script for quick setup. Set MaxMemoryPerShellMB to at least 1024. Enable LocalAccountTokenFilterPolicy for local admin accounts. Consider PSRP over WinRM for better performance. Always store Windows passwords in Ansible Vault. Test with win_ping before running playbooks.