Introduction
Connection plugins are how Ansible communicates with managed hosts. While SSH is the default, Ansible supports multiple connection types for different platforms — Windows (WinRM/PSRP), network devices (network_cli, httpapi, netconf), containers (docker, podman), and local execution.
Understanding connection plugins lets you automate heterogeneous environments with a single Ansible control node.
Available Connection Plugins
| Plugin | Use Case | Transport |
|---|---|---|
| `ansible.builtin.ssh` | Linux/Unix hosts (default) | OpenSSH |
| `ansible.builtin.paramiko_ssh` | SSH without OpenSSH | Python paramiko |
| `ansible.builtin.local` | Run on control node | Direct |
| `ansible.builtin.winrm` | Windows hosts | WinRM/HTTPS |
| `ansible.builtin.psrp` | Windows via PowerShell | PSRP/WSMan |
| `ansible.netcommon.network_cli` | Network device CLI | SSH |
| `ansible.netcommon.httpapi` | Network device REST API | HTTPS |
| `ansible.netcommon.netconf` | Network device NETCONF | SSH/NETCONF |
| `community.docker.docker` | Docker containers | Docker API |
| `containers.podman.podman` | Podman containers | Podman API |
| `community.libvirt.libvirt_lxc` | LXC containers | libvirt |
| `kubectl` | Kubernetes pods | kubectl |
SSH Connection (Default)
Basic Configuration
```ini
[defaults] remote_user = ansible private_key_file = ~/.ssh/ansible_key host_key_checking = False
[ssh_connection] pipelining = True ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o PreferAuthenticatedKeyExchange=yes control_path_dir = ~/.ansible/cp ```
Inventory Configuration
```ini
[webservers] web1.example.com ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/web_key web2.example.com ansible_port=2222
[webservers:vars] ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no' ```
SSH Multiplexing
```yaml
ansible_ssh_common_args: >- -o ControlMaster=auto -o ControlPersist=600s -o PreferAuthenticatedKeyExchange=yes ```
SSH Pipelining
```ini
[ssh_connection] pipelining = True ```
Pipelining executes modules without writing temporary files to the remote host, significantly improving performance.
WinRM Connection (Windows)
Windows Host Setup
```powershell
winrm quickconfig -force
$cert = New-SelfSignedCertificate -DnsName "server.example.com" -CertStoreLocation Cert:\LocalMachine\My winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=\"server.example.com\";CertificateThumbprint=\"$($cert.Thumbprint)\"}"
Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true Set-Item WSMan:\localhost\Service\Auth\Certificate -Value $true ```
Inventory for Windows
```ini [windows] win1.example.com win2.example.com
[windows:vars] ansible_connection=winrm ansible_winrm_transport=ntlm ansible_winrm_server_cert_validation=ignore ansible_user=Administrator ansible_password=SecurePassword123! ansible_port=5986 ansible_winrm_scheme=https ```
PSRP (PowerShell Remoting Protocol)
```ini
[windows:vars] ansible_connection=psrp ansible_psrp_auth=negotiate ansible_psrp_cert_validation=ignore ```
Network Device Connections
network_cli (CLI over SSH)
```yaml
[cisco_routers] router1.example.com
[cisco_routers:vars] ansible_connection: ansible.netcommon.network_cli ansible_network_os: cisco.ios.ios ansible_user: admin ansible_password: "{{ vault_network_password }}" ansible_become: true ansible_become_method: enable ansible_become_password: "{{ vault_enable_password }}" ```
```yaml
- name: Configure Cisco routers
hosts: cisco_routers
gather_facts: false
tasks:
-
name: Get running config cisco.ios.ios_command: commands: - show running-config register: config
-
name: Configure interface cisco.ios.ios_config: lines: - description Managed by Ansible - ip address 10.0.1.1 255.255.255.0 parents: interface GigabitEthernet0/1 ```
-
httpapi (REST API)
```yaml
[arista_switches] switch1.example.com
[arista_switches:vars] ansible_connection: ansible.netcommon.httpapi ansible_network_os: arista.eos.eos ansible_httpapi_use_ssl: true ansible_httpapi_validate_certs: false ansible_user: admin ansible_password: "{{ vault_switch_password }}" ```
netconf (XML-based)
```yaml
[juniper_routers] juniper1.example.com
[juniper_routers:vars] ansible_connection: ansible.netcommon.netconf ansible_network_os: junipernetworks.junos.junos ansible_user: admin ansible_password: "{{ vault_juniper_password }}" ```
Local Connection
```yaml
- name: Local tasks
hosts: localhost
connection: local
tasks:
-
name: Create local directory ansible.builtin.file: path: /tmp/reports state: directory
-
name: Generate report ansible.builtin.template: src: report.j2 dest: /tmp/reports/daily.html ```
-
Container Connections
Docker
```yaml
- name: Configure Docker containers
hosts: docker_containers
connection: community.docker.docker
tasks:
- name: Install package inside container ansible.builtin.apt: name: nginx state: present ```
```ini
[docker_containers] my_container ansible_docker_extra_args="--tlsverify" ```
Kubernetes Pods
```ini
[k8s_pods] my-pod ansible_connection=kubectl ansible_kubectl_namespace=production ```
Per-Host Connection Override
```yaml
[linux_servers] web1.example.com ansible_connection=ssh
[windows_servers] win1.example.com ansible_connection=winrm
[network_devices] router1.example.com ansible_connection=network_cli ansible_network_os=cisco.ios.ios
[containers] app_container ansible_connection=docker
[local] localhost ansible_connection=local ```
Playbook to Test All Connection Types
```yaml
-
name: Verify Linux connectivity hosts: linux_servers gather_facts: false tasks:
- name: Ping Linux hosts ansible.builtin.ping:
-
name: Verify Windows connectivity hosts: windows_servers gather_facts: false tasks:
- name: Ping Windows hosts ansible.windows.win_ping:
-
name: Verify network devices hosts: network_devices gather_facts: false tasks:
- name: Get device facts cisco.ios.ios_facts: gather_subset: min ```
Troubleshooting
Debug Connection Issues
```bash
ansible web1.example.com -m ping -vvvv
ansible win1.example.com -m ansible.windows.win_ping -vvv
ansible-config dump | grep CONNECTION ```
Common Issues
SSH: "Permission denied" ```bash
chmod 600 ~/.ssh/ansible_key ssh -i ~/.ssh/ansible_key user@host ```
WinRM: "Connection refused" ```powershell
winrm enumerate winrm/config/listener
netsh advfirewall firewall show rule name="Windows Remote Management (HTTPS-In)" ```
network_cli: "Unable to open shell" ```yaml
ansible_network_os: cisco.ios.ios # not just "ios" ```
Connection Plugin Variables Reference
| Variable | Description |
|---|---|
| `ansible_connection` | Connection plugin to use |
| `ansible_host` | Hostname/IP to connect to |
| `ansible_port` | Connection port |
| `ansible_user` | Remote username |
| `ansible_password` | Remote password (use vault!) |
| `ansible_ssh_private_key_file` | SSH private key |
| `ansible_become` | Enable privilege escalation |
| `ansible_become_method` | Escalation method (sudo, enable) |
| `ansible_network_os` | Network OS platform |
| `ansible_winrm_transport` | WinRM auth method |
Related Articles
- Ansible SSH Configuration Guide
- Ansible WinRM over SSH with PSRP
- Ansible Network Automation
- Ansible Docker Automation
- Ansible Kubernetes Guide
Conclusion
Connection plugins are the foundation of Ansible's multi-platform capabilities. Choose the right plugin for each host type, configure authentication securely with Ansible Vault, and use pipelining/multiplexing for performance. Test connectivity with verbose mode before building complex playbooks.