Ansible wait_for_connection — Wait for Host to Become Reachable

Introduction

ansible.builtin.wait_for_connection waits until Ansible can successfully connect to a host. Unlike wait_for (which checks ports), wait_for_connection verifies the full Ansible connection stack — SSH authentication, Python availability, and module execution. It's essential after reboots, cloud instance launches, and network reconfigurations.

Basic Usage

---
- name: wait_for_connection examples
  hosts: all
  tasks:
    - name: Reboot the server
      ansible.builtin.reboot:
        reboot_timeout: 300
      # Note: reboot module has built-in wait — but sometimes you need manual control

    - name: Wait for host to come back
      ansible.builtin.wait_for_connection:
        timeout: 300      # Max seconds to wait
        delay: 10         # Seconds before first check
        sleep: 5          # Seconds between checks

After Manual Reboot

    - name: Schedule reboot
      ansible.builtin.command:
        cmd: shutdown -r +1 "Ansible-initiated reboot"

    - name: Wait for host to come back online
      ansible.builtin.wait_for_connection:
        delay: 75         # Wait at least 75s (shutdown in 60s + boot time)
        timeout: 600      # Give up after 10 minutes
        sleep: 10

After Cloud Provisioning

- name: Provision and configure
  hosts: localhost
  connection: local
  tasks:
    - name: Launch EC2 instance
      amazon.aws.ec2_instance:
        name: webserver
        instance_type: t3.micro
        image_id: ami-0abcdef1234567890
        key_name: deploy-key
        state: running
        wait: true
      register: ec2

    - name: Add to inventory
      ansible.builtin.add_host:
        name: new-server
        ansible_host: "{{ ec2.instances[0].public_ip_address }}"
        ansible_user: ec2-user
        ansible_ssh_private_key_file: ~/.ssh/deploy-key.pem
        groups: new_instances

- name: Configure new instances
  hosts: new_instances
  gather_facts: false
  tasks:
    - name: Wait for SSH and Python
      ansible.builtin.wait_for_connection:
        timeout: 300
        delay: 30

    - name: Now gather facts
      ansible.builtin.setup:

    - name: Install packages
      ansible.builtin.package:
        name: nginx
        state: present

After Kernel Upgrade

    - name: Upgrade kernel
      ansible.builtin.package:
        name: "linux-image-*"
        state: latest
      register: kernel_upgrade

    - name: Reboot for new kernel
      ansible.builtin.command:
        cmd: reboot
      when: kernel_upgrade.changed
      async: 0
      poll: 0

    - name: Wait for host after kernel reboot
      ansible.builtin.wait_for_connection:
        delay: 30
        timeout: 600
      when: kernel_upgrade.changed

    - name: Verify new kernel
      ansible.builtin.command:
        cmd: uname -r
      register: kernel
      changed_when: false

    - name: Show kernel version
      ansible.builtin.debug:
        msg: "Kernel: {{ kernel.stdout }}"

After Network Changes

    - name: Change IP address
      ansible.builtin.template:
        src: netplan.yaml.j2
        dest: /etc/netplan/01-config.yaml
      register: network_changed

    - name: Apply network config
      ansible.builtin.command:
        cmd: netplan apply
      when: network_changed.changed

    - name: Update connection details
      ansible.builtin.set_fact:
        ansible_host: "{{ new_ip_address }}"
      when: network_changed.changed

    - name: Wait for new IP to be reachable
      ansible.builtin.wait_for_connection:
        timeout: 120
        delay: 5
      when: network_changed.changed

Windows (WinRM)

- name: Reboot Windows server
  hosts: windows
  tasks:
    - name: Install updates
      ansible.windows.win_updates:
        category_names:
          - SecurityUpdates
          - CriticalUpdates
        reboot: false
      register: updates

    - name: Reboot if needed
      ansible.windows.win_reboot:
      when: updates.reboot_required

    - name: Wait for WinRM
      ansible.builtin.wait_for_connection:
        timeout: 600
        delay: 30
      when: updates.reboot_required

wait_for_connection vs wait_for vs reboot

Featurewait_for_connectionwait_forreboot
ChecksFull Ansible connectionPort/file/stringReboot + reconnect
Verifies Python✅❌✅
Verifies auth✅❌✅
Use caseAfter reboot/provisionPort readinessSafe reboot
Runs onControllerRemote (or local)Remote

Parameters

ParameterDefaultDescription
timeout600Max seconds to wait
delay0Seconds before first attempt
sleep1Seconds between attempts
connect_timeout5Per-attempt connection timeout

Rolling Reboot Pattern

- name: Rolling reboot
  hosts: webservers
  serial: 1
  tasks:
    - name: Remove from LB
      ansible.builtin.uri:
        url: "https://lb.example.com/api/remove/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost

    - name: Reboot
      ansible.builtin.command:
        cmd: reboot
      async: 0
      poll: 0

    - name: Wait for reconnection
      ansible.builtin.wait_for_connection:
        delay: 30
        timeout: 300

    - name: Verify health
      ansible.builtin.uri:
        url: "http://localhost:8080/health"
        status_code: 200
      register: health
      until: health.status == 200
      retries: 12
      delay: 5

    - name: Add back to LB
      ansible.builtin.uri:
        url: "https://lb.example.com/api/add/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost

Troubleshooting

IssueSolution
Times outIncrease timeout; check host actually boots
Connects too earlyIncrease delay to wait for full boot
Auth failuresVerify SSH key/password; check user account
Python not foundBootstrap Python first with raw module
Wrong IP after rebootUpdate ansible_host with set_fact before waiting

Best Practices

  1. Set delay appropriately — don't waste attempts during shutdown/boot
  2. Use reboot module when possible — handles the full cycle
  3. Increase timeout for cloud — cloud instances can take 3-5 minutes
  4. Set gather_facts: false — gather after connection succeeds
  5. Pair with health checks — connection ≠ application ready

Conclusion

wait_for_connection is the safest way to verify a host is fully reachable after reboots, provisioning, or network changes. Unlike port checks, it validates the complete Ansible connection — SSH, authentication, and Python. Use it between disruptive operations and configuration tasks to ensure your automation doesn't fail on unreachable hosts.