ScreenshotNeo

BlogHow-to

How to Connect to Windows Ansible From Ubuntu

Connect Ansible on Ubuntu to Windows with PSRP, WinRM, or SSH, including inventory, authentication, testing, troubleshooting, and security.

By the ScreenshotNeo team29 September 20269 min read

How to Connect to Windows Ansible From Ubuntu

Direct answer: Run Ansible on Ubuntu as the control node and configure each Windows machine as a managed node. Use PSRP or WinRM when your environment already uses Windows Remote Management, Active Directory, or Windows delegation. Use SSH when Win32-OpenSSH is configured and key-based authentication is preferable. The current Ansible Windows guide documents PSRP, WinRM, and SSH for Windows Server 2016, Windows 10, and newer targets. See Ansible’s Windows setup guide.

The basic sequence is:

  1. Install Ansible on Ubuntu.
  2. Prepare WinRM/PSRP or Win32-OpenSSH on Windows.
  3. Create an inventory with the correct connection plugin and authentication variables.
  4. Test network access and credentials with win_ping.
  5. Run a small ad hoc command before applying a larger playbook.

1. Choose PSRP, WinRM, or SSH

Transport Use it when Ubuntu requirement Windows requirement
PSRP You want PowerShell remoting through WinRM and a modern Ansible plugin. pypsrp>=0.4.0,<1.0.0 WinRM listener, authentication policy, and firewall access.
WinRM Your organization already standardizes on WinRM and its authentication settings. Ansible’s WinRM support and its Python dependencies. WinRM listener, authentication policy, and firewall access.
SSH You prefer OpenSSH, keys, or a non-domain setup. OpenSSH client and Ansible 2.18 or newer for official Windows SSH support. Win32-OpenSSH server, account policy, authorized keys, and firewall access.

PSRP and WinRM both use Windows Remote Management. PSRP runs commands through PowerShell and requires the controller-side pypsrp package. SSH is also supported for Windows; Ansible’s documentation describes it as an alternative to the traditional PSRP and WinRM plugins. Read the WinRM connection documentation and Windows SSH documentation before choosing.

Ubuntu can manage Windows through PSRP, WinRM, or SSH when the matching service and inventory settings are configured.
Ubuntu can manage Windows through PSRP, WinRM, or SSH when the matching service and inventory settings are configured.

2. Install Ansible on Ubuntu

Use your team’s approved Ubuntu package or Python installation method. A virtual environment keeps controller dependencies separate:

sudo apt update
sudo apt install -y python3-venv python3-pip openssh-client
python3 -m venv ~/venvs/ansible
source ~/venvs/ansible/bin/activate
python -m pip install --upgrade pip ansible
ansible --version

For PSRP, install the documented dependency range:

python -m pip install 'pypsrp>=0.4.0,<1.0.0'

Keep the virtual environment active whenever you run Ansible, or install the same packages into the environment that actually executes your automation jobs.

3. Prepare the Windows host

PSRP or WinRM preparation

On Windows, create and start a WinRM listener, choose HTTP or HTTPS, enable only the authentication mechanisms your policy permits, and allow the selected port through the firewall. HTTPS and a trusted certificate are preferred for production. The exact commands depend on your domain policy, certificate infrastructure, and whether the host is domain joined, so follow your organization’s Windows remoting standard and the official WinRM variables and authentication guidance.

WinRM commands run in a non-interactive network-logon session. A command that succeeds in an interactive PowerShell window can therefore fail under Ansible because of permissions, profile differences, or a second network hop.

SSH preparation

Install Win32-OpenSSH Server, start the sshd service, configure the permitted shell and authentication methods, add the controller’s public key to the Windows account’s authorized keys, and open the SSH port in Windows Firewall. Test the service from Ubuntu with ordinary SSH before involving Ansible.

ssh -vvv WINDOWS_USER@192.0.2.20

GSSAPI/Kerberos requires Kerberos configuration on Ubuntu and matching Windows OpenSSH settings. The SSH plugin cannot obtain a Kerberos TGT from an explicit username/password combination; use the documented Kerberos workflow instead.

4. Create a PSRP inventory

Create inventory.yml. Store the password in Ansible Vault or an external secret store rather than committing it:

all:
  children:
    windows:
      hosts:
        win01:
          ansible_host: 192.0.2.20
          ansible_user: 'CONTOSO\\ansible'
          ansible_password: '{{ vault_windows_password }}'
          ansible_connection: psrp
          ansible_psrp_auth: negotiate
          ansible_psrp_cert_validation: ignore

ignore is useful for an initial lab test with a self-signed certificate. In production, issue a certificate trusted by the Ubuntu controller and validate it instead. Authentication values must match what the Windows listener permits. Common choices include Kerberos or Negotiate for domain environments and other methods documented by the PSRP plugin.

Create a vault file and encrypt it:

ansible-vault create group_vars/windows/vault.yml
# Add:
# vault_windows_password: 'replace-with-the-real-secret'

ansible-playbook -i inventory.yml --ask-vault-pass playbook.yml

5. Create a WinRM inventory

WinRM uses the ansible_winrm_* variable family. A minimal HTTPS example looks like this:

all:
  children:
    windows:
      hosts:
        win01:
          ansible_host: 192.0.2.20
          ansible_user: 'CONTOSO\\ansible'
          ansible_password: '{{ vault_windows_password }}'
          ansible_connection: winrm
          ansible_port: 5986
          ansible_winrm_transport: kerberos
          ansible_winrm_server_cert_validation: validate

For a lab certificate, the corresponding validation setting can be relaxed temporarily, but disabling certificate validation should not become your normal production configuration. Do not treat disabled encryption as a fix for an authentication problem. Verify the transport, port, certificate name, and authentication protocol together.

6. Create an SSH inventory

all:
  children:
    windows:
      hosts:
        win01:
          ansible_host: 192.0.2.20
          ansible_user: ansible
          ansible_connection: ssh
          ansible_port: 22
          ansible_ssh_private_key_file: ~/.ssh/windows_ansible_ed25519
          ansible_shell_type: powershell

ansible_shell_type: powershell tells Ansible how to wrap commands for the Windows shell. If the server exposes a different configured shell, use the value required by that OpenSSH installation. Password authentication is possible when enabled by sshd, but keys are generally easier to rotate and audit.

7. Verify the connection in layers

Start with DNS and TCP reachability, then test the native transport, then use Ansible’s Windows module.

Check the port with cURL

For WinRM over HTTPS, this confirms that Ubuntu can reach the listener. It does not authenticate an Ansible session:

curl -vk --connect-timeout 10 https://192.0.2.20:5986/wsman

Check reachability with Python

python3 - <<'PY'
import socket
host = '192.0.2.20'
port = 5986
with socket.create_connection((host, port), timeout=10):
    print(f'{host}:{port} is reachable')
PY

Check reachability with Node.js

node - <<'NODE'
const net = require('net');
const socket = net.createConnection({ host: '192.0.2.20', port: 5986, timeout: 10000 });
socket.on('connect', () => { console.log('192.0.2.20:5986 is reachable'); socket.end(); });
socket.on('timeout', () => { console.error('connection timed out'); socket.destroy(); process.exitCode = 1; });
socket.on('error', err => { console.error(err.message); process.exitCode = 1; });
NODE

Run Ansible’s Windows ping

ansible windows -i inventory.yml -m ansible.windows.win_ping --ask-vault-pass

A successful result means Ansible authenticated and executed a Windows module. Follow with a narrowly scoped command:

ansible windows -i inventory.yml -m ansible.windows.win_command -a 'whoami' --ask-vault-pass

For SSH, run ssh -vvv first, then repeat the win_ping command with the SSH inventory.

8. Run a first playbook safely

---
- name: Verify Windows management
  hosts: windows
  gather_facts: false
  tasks:
    - name: Confirm Ansible can use PowerShell
      ansible.windows.win_ping:

    - name: Display the account used by the session
      ansible.windows.win_command: whoami
      register: identity

    - name: Print the account
      ansible.builtin.debug:
        var: identity.stdout

Use gather_facts: false while diagnosing connectivity. Once the connection is stable, enable facts only when the playbook needs them; this reduces startup work across many hosts.

9. Troubleshooting common failures

Symptom Likely cause Fix
win_ping times out Firewall, wrong port, no listener, routing, or DNS issue. Test the exact IP and port with curl or Python, inspect the Windows listener, and check firewall rules.
401 or authentication failure Wrong username format, disabled account, unsupported authentication method, or lockout. Confirm the account, password, domain format, and enabled listener methods. Inspect the newest Windows Security event 4625 entry and its status/substatus codes.
Certificate validation error Certificate name, trust chain, or expiration does not match. Use a certificate trusted by Ubuntu and connect using its matching name. Relax validation only for a controlled lab test.
PSRP import or dependency error pypsrp is missing or outside the supported range. Install pypsrp>=0.4.0,<1.0.0 in the same Python environment as Ansible.
SSH connection refused sshd is stopped, the port is blocked, or the service listens on another port. Check the Windows service, firewall, configured port, and ordinary SSH from Ubuntu.
SSH permission denied Wrong account, key permissions, missing authorized key, or disallowed authentication method. Use ssh -vvv, verify the Windows account’s authorized keys and sshd_config, and confirm the key path in inventory.
Command works interactively but not in Ansible WinRM uses a non-interactive network logon. Check profile-dependent paths, local rights, environment variables, and whether the operation needs delegation.
Second network resource is inaccessible Double-hop delegation is not configured. Use an appropriate Kerberos or CredSSP delegation design, or stage the required file locally. Do not place reusable passwords in scripts.
Local administrator behaves unexpectedly Local-account token filtering or missing logon rights. Review the account’s rights and Windows security policy; test with a purpose-created automation account.

Run with increased verbosity only while diagnosing:

ansible windows -i inventory.yml -m ansible.windows.win_ping -vvvv --ask-vault-pass

Verbose output can expose connection details, so avoid sharing logs that contain credentials, tokens, or private host information.

10. Security, performance, and reliability practices

  • Secrets: Use Ansible Vault or an external secret manager. Keep passwords out of inventory committed to source control.
  • Network exposure: Restrict WinRM and SSH ports to controller networks with firewalls. Prefer HTTPS for WinRM and secure SSH configuration.
  • Least privilege: Use a dedicated account with only the rights required by the playbooks.
  • Delegation: Design double-hop access explicitly. A successful first connection does not prove access to a second file share or database.
  • Fact gathering: Disable it for connectivity checks and enable it only when needed.
  • Concurrency: Start with a small batch using serial in production playbooks, then increase gradually after measuring the controller and Windows hosts.
  • Retries: Add retries for transient service readiness, but do not hide persistent authentication or certificate errors with long retry loops.
  • Version control: Pin Ansible and controller dependencies in a requirements file or managed execution environment so upgrades are deliberate.
A successful first WinRM session does not automatically grant access to a second network resource.
A successful first WinRM session does not automatically grant access to a second network resource.

Or skip the browser setup

If your next task is capturing a website for documentation, visual regression, or an agent workflow, ScreenshotNeo provides a single HTTP request instead of maintaining a browser controller. Cookie and consent banners are accepted and removed before the shot, along with more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf.

See the ScreenshotNeo API documentation for all options:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

There are 1,000 screenshots per month free with no card. Paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account.

FAQ

Can Ubuntu manage Windows without installing Ansible on Windows?

Yes. Ubuntu is the control node; Windows needs the selected remoting service and the permissions required by your playbooks.

Is PSRP better than WinRM?

PSRP is the newer PowerShell-oriented plugin, while WinRM may fit an existing WinRM standard. Choose based on authentication, delegation, certificate, and operational requirements.

Can I use SSH for domain-joined Windows servers?

Yes, when Win32-OpenSSH and the required Kerberos/GSSAPI configuration are in place. Test ordinary SSH and document the authentication policy.

Why does a network share fail after win_ping succeeds?

The share may require a second network hop. Configure delegation deliberately or transfer credentials and files through a safer, explicit mechanism.

What should I check first when win_ping fails?

Check the host and port, then the listener, firewall, username format, authentication method, certificate policy, and Windows Security event 4625 details.