AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible wait_for Module: Wait for Conditions, Ports & Files (Guide)

By Luca Berton · Published 2024-01-01 · Category: troubleshooting

Complete guide to Ansible wait_for module. Wait for ports to open, files to appear, services to start, connections to drain, and processes to finish.

The ansible.builtin.wait_for module pauses playbook execution until a specified condition is met — a port is open, a file exists, a string appears in a file, or connections drain. It's essential for service readiness checks, deployment orchestration, and handling reboots.

Wait for a Port

Port to Open (Service Ready)

- name: Start application
  ansible.builtin.systemd:
    name: myapp
    state: started

- name: Wait for app to listen on port 8080
  ansible.builtin.wait_for:
    port: 8080
    delay: 5           # Wait 5s before first check
    timeout: 60        # Fail after 60s

- name: Wait for remote port
  ansible.builtin.wait_for:
    host: db.example.com
    port: 5432
    timeout: 120

Port to Close (Connections Drained)

- name: Stop accepting new connections
  ansible.builtin.command: /opt/app/drain.sh

- name: Wait for all connections to close
  ansible.builtin.wait_for:
    port: 8080
    state: drained
    timeout: 120

Wait for Port After Restart

- name: Restart service
  ansible.builtin.systemd:
    name: myapp
    state: restarted

- name: Wait for service to be ready
  ansible.builtin.wait_for:
    port: "{{ app_port }}"
    delay: 3
    timeout: 30

See also: Ansible 2.17.0-rc1: Elevating Automation with ‘Gallows Pole’

Wait for a File

File to Exist

- name: Start background job
  ansible.builtin.command: /opt/batch/run.sh &

- name: Wait for output file
  ansible.builtin.wait_for:
    path: /opt/batch/output/results.csv
    timeout: 300

File to Contain a String

- name: Start application
  ansible.builtin.systemd:
    name: myapp
    state: started

- name: Wait for "Server started" in log
  ansible.builtin.wait_for:
    path: /var/log/myapp/app.log
    search_regex: "Server started on port"
    timeout: 60

# Wait for specific pattern
- name: Wait for database migration complete
  ansible.builtin.wait_for:
    path: /var/log/myapp/migrate.log
    search_regex: "Migrations complete|Already up to date"
    timeout: 120

File to Be Absent

- name: Wait for lock file to be removed
  ansible.builtin.wait_for:
    path: /var/run/myapp.lock
    state: absent
    timeout: 60

Wait for Connection (After Reboot)

wait_for_connection is purpose-built for reconnecting after reboots:

- name: Reboot server
  ansible.builtin.reboot:
    reboot_timeout: 300

# Or manually:
- name: Reboot server
  ansible.builtin.command: shutdown -r now
  async: 1
  poll: 0

- name: Wait for server to come back
  ansible.builtin.wait_for_connection:
    connect_timeout: 10
    sleep: 5
    delay: 30        # Don't start checking for 30s
    timeout: 300

See also: Ansible Development: Write Custom Modules, Plugins & Collections

Real-World Patterns

Rolling Deployment with Health Checks

- hosts: webservers
  serial: 1
  tasks:
    - name: Remove from load balancer
      ansible.builtin.command: "lb-ctl drain {{ inventory_hostname }}"
      delegate_to: "{{ lb_host }}"

    - name: Wait for connections to drain
      ansible.builtin.wait_for:
        port: 8080
        state: drained
        timeout: 60

    - name: Deploy new version
      ansible.builtin.include_role:
        name: deploy

    - name: Wait for application to start
      ansible.builtin.wait_for:
        port: 8080
        delay: 5
        timeout: 30

    - name: Wait for health endpoint
      ansible.builtin.uri:
        url: "http://localhost:8080/health"
      register: health
      retries: 10
      delay: 5
      until: health.status == 200

    - name: Re-enable in load balancer
      ansible.builtin.command: "lb-ctl enable {{ inventory_hostname }}"
      delegate_to: "{{ lb_host }}"

Database Startup Chain

- name: Start PostgreSQL
  ansible.builtin.systemd:
    name: postgresql
    state: started

- name: Wait for PostgreSQL to accept connections
  ansible.builtin.wait_for:
    port: 5432
    delay: 2
    timeout: 30

- name: Start Redis
  ansible.builtin.systemd:
    name: redis
    state: started

- name: Wait for Redis
  ansible.builtin.wait_for:
    port: 6379
    timeout: 15

- name: Start application (depends on DB + Redis)
  ansible.builtin.systemd:
    name: myapp
    state: started

- name: Wait for app health check
  ansible.builtin.wait_for:
    port: 8080
    delay: 5
    timeout: 60

Wait for Cloud Instance

- name: Create EC2 instance
  amazon.aws.ec2_instance:
    name: webserver
    instance_type: t3.medium
    image_id: "{{ ami_id }}"
  register: ec2

- name: Wait for SSH to be ready
  ansible.builtin.wait_for:
    host: "{{ ec2.instances[0].public_ip_address }}"
    port: 22
    delay: 10
    timeout: 300
  delegate_to: localhost

Parameters Reference

ParameterDescriptionDefault
portPort number to check
hostHost to check127.0.0.1
pathFile path to check
statestarted, stopped, present, absent, drainedstarted
delaySeconds to wait before first check0
timeoutSeconds before giving up300
sleepSeconds between checks1
search_regexRegex to match in file
exclude_hostsHosts to ignore for drained
connect_timeoutSeconds for each connection attempt5
msgCustom failure message

FAQ

What does wait_for do in Ansible?

The wait_for module pauses playbook execution until a specified condition is met: a TCP port opens, a file appears/disappears, or a regex pattern is found in a file. It's used to wait for services to start, connections to drain, or processes to complete.

What is the difference between wait_for and wait_for_connection?

wait_for checks for ports, files, or strings on target hosts. wait_for_connection specifically waits for Ansible to be able to connect (SSH/WinRM) to a host — designed for use after reboots.

How do I wait for a service to be ready?

Use wait_for with the service port: wait_for: port=8080 delay=5 timeout=60. For HTTP health checks, use the uri module with retries and until instead.

What happens when wait_for times out?

The task fails with a timeout error and the playbook stops (unless ignore_errors: true is set). Use the msg parameter to provide a helpful failure message.

Can I wait for multiple conditions?

Not in a single task. Use separate wait_for tasks for each condition, or use ansible.builtin.async with poll: 0 to check multiple conditions in parallel.

See also: Ansible Delete File & Remove File: file Module absent State Guide

Conclusion

  • Port checks: port: 8080 with state: started (open) or drained (closed)
  • File checks: path: with state: present/absent or search_regex
  • After reboots: Use wait_for_connection instead
  • Always set timeout — don't let tasks hang forever
  • Use delay to skip the initial startup period

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home