Ansible Windows WinRM Setup — Remote Management Guide
Introduction
Ansible manages Windows hosts through WinRM (Windows Remote Management) instead of SSH. Setting up WinRM correctly — with HTTPS, proper authentication, and firewall rules — is the critical first step for Windows automation. This guide covers everything from basic setup to enterprise GPO deployment.
Prerequisites
# On the Ansible controller (Linux)
pip install pywinrm
pip install pywinrm[credssp] # For CredSSP authentication
# Verify
python -c "import winrm; print(winrm.__version__)"
Quick WinRM Setup (PowerShell)
Run on each Windows host as Administrator:
# Enable WinRM with HTTPS
winrm quickconfig -transport:https
# Or use the Ansible setup script (recommended)
$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 WinRM Configuration
# Step 1: Enable WinRM service
Enable-PSRemoting -Force
# Step 2: Create self-signed certificate
$cert = New-SelfSignedCertificate -DnsName "$env:COMPUTERNAME" `
-CertStoreLocation Cert:\LocalMachine\My `
-NotAfter (Get-Date).AddYears(5)
# Step 3: Create HTTPS listener
winrm create winrm/config/Listener?Address=*+Transport=HTTPS `
"@{Hostname=`"$env:COMPUTERNAME`"; CertificateThumbprint=`"$($cert.Thumbprint)`"}"
# Step 4: Open firewall port
New-NetFirewallRule -DisplayName "WinRM HTTPS" `
-Direction Inbound -LocalPort 5986 `
-Protocol TCP -Action Allow
# Step 5: Configure authentication
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
Set-Item -Path WSMan:\localhost\Service\Auth\CredSSP -Value $true
# Step 6: Allow unencrypted (only for testing with HTTP)
# Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true
Ansible Inventory for Windows
# inventory.yml
all:
children:
windows:
hosts:
win-web01:
ansible_host: 192.168.1.100
win-web02:
ansible_host: 192.168.1.101
win-db01:
ansible_host: 192.168.1.200
vars:
ansible_user: ansible_admin
ansible_password: "{{ vault_windows_password }}"
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
ansible_port: 5986
ansible_winrm_scheme: https
Authentication Methods
# NTLM (most common, works with local and domain accounts)
ansible_winrm_transport: ntlm
# Kerberos (Active Directory, most secure)
ansible_winrm_transport: kerberos
ansible_winrm_kerberos_delegation: true
# CredSSP (supports double-hop authentication)
ansible_winrm_transport: credssp
# Basic (only over HTTPS, local accounts only)
ansible_winrm_transport: basic
Kerberos Setup
# On the Ansible controller
pip install pywinrm[kerberos]
sudo apt install krb5-user # Debian/Ubuntu
sudo dnf install krb5-workstation # RHEL
# Configure /etc/krb5.conf
[realms]
EXAMPLE.COM = {
kdc = dc01.example.com
admin_server = dc01.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
# Inventory with Kerberos
windows:
vars:
ansible_user: ansible_admin@EXAMPLE.COM
ansible_winrm_transport: kerberos
ansible_connection: winrm
ansible_port: 5986
Test Connection
# Ping Windows hosts
ansible windows -m win_ping -i inventory.yml
# Gather facts
ansible windows -m setup -i inventory.yml
GPO Deployment (Enterprise)
# Deploy WinRM settings via Group Policy
# Computer Configuration → Administrative Templates → Windows Components → Windows Remote Management
# GPO settings:
# 1. Allow remote server management through WinRM: Enabled
# - IPv4 filter: * (or specific subnet)
# 2. Turn on Script Execution: Allow all scripts
# 3. Windows Firewall: Allow inbound on 5985/5986
Common Windows Playbook
---
- name: Configure Windows servers
hosts: windows
tasks:
- name: Install IIS
ansible.windows.win_feature:
name: Web-Server
include_management_tools: true
state: present
- name: Create website directory
ansible.windows.win_file:
path: C:\inetpub\myapp
state: directory
- name: Deploy configuration
ansible.windows.win_template:
src: web.config.j2
dest: C:\inetpub\myapp\web.config
- name: Ensure service is running
ansible.windows.win_service:
name: W3SVC
start_mode: auto
state: started
- name: Open firewall port
community.windows.win_firewall_rule:
name: "HTTP Inbound"
localport: 80
action: allow
direction: in
protocol: tcp
state: present
enabled: true
- name: Install Windows updates
ansible.windows.win_updates:
category_names:
- SecurityUpdates
- CriticalUpdates
reboot: true
reboot_timeout: 3600
register: updates
- name: Show update results
ansible.builtin.debug:
msg: "{{ updates.installed_update_count }} updates installed"
WinRM Verification Commands
# Check WinRM service status
Get-Service WinRM
# List listeners
winrm enumerate winrm/config/Listener
# Check configuration
winrm get winrm/config
# Test WinRM locally
Test-WSMan -ComputerName localhost
# Check authentication settings
winrm get winrm/config/Service/Auth
# Check HTTPS certificate
Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -match $env:COMPUTERNAME }
Troubleshooting
| Issue | Solution |
|---|---|
| Connection refused | Enable WinRM: Enable-PSRemoting -Force |
| SSL certificate error | Add ansible_winrm_server_cert_validation: ignore |
| Authentication failed | Check username format: user (local) vs user@DOMAIN (Kerberos) |
| "Access denied" | User must be in local Administrators group |
| Timeout errors | Check firewall port 5986, increase ansible_winrm_operation_timeout_sec |
| Double-hop fails | Use CredSSP: ansible_winrm_transport: credssp |
| Kerberos "Clock skew" | Sync time between controller and DC: ntpdate dc01.example.com |
Best Practices
- Always use HTTPS (port 5986) — never HTTP (5985) in production
- Use Kerberos for Active Directory environments — most secure
- Use CredSSP when double-hop auth is needed (accessing network shares)
- Deploy WinRM via GPO — don't manually configure each host
- Use
win_pingto verify before running playbooks — catches auth issues early - Store passwords in Vault — never plain text in inventory
Conclusion
WinRM setup is the gateway to Windows automation with Ansible. Once configured with HTTPS and proper authentication, you have full access to Windows modules — win_feature, win_service, win_updates, win_package, and hundreds more. The initial setup investment pays off immediately when you can manage your entire Windows fleet as code.