Solving Ansible 'Timeout when waiting for host:port' Errors

beginner🔧 Ansible2026-07-12| Linux (Ubuntu/CentOS/Debian), Ansible 2.9+, targeting services like MySQL, PostgreSQL, or Nginx.

Error Message

FAILED! => {"elapsed": 30, "msg": "Timeout when waiting for 127.0.0.1:3306"}
#ansible#devops#troubleshooting#linux#automation

TL;DR: The Quick Fix

Most of the time, this error occurs because a service—like a heavy Java application or a database—takes longer to initialize than Ansible's default 30-second window. To fix it, you need to give the service some breathing room by increasing the timeout and adding a delay.

- name: Wait for MySQL to be ready
  wait_for:
    host: 127.0.0.1
    port: 3306
    delay: 10     # Don't even check for the first 10 seconds
    timeout: 90   # Give it up to 90 seconds total
    state: started

In this configuration, Ansible sleeps for 10 seconds, then polls the port until it opens or until the 90-second timer hits zero.

Why Is This Happening?

When you see "elapsed": 30 in your error log, it means the wait_for module reached its time limit without establishing a successful TCP connection. It isn't necessarily a bug in your code; it's often just a timing mismatch.

Typical causes include:

  • Database Migrations: A new MySQL or PostgreSQL container might be busy building tables or importing a 500MB SQL dump on the first boot.
  • JVM Warmup: Java-based tools like Jenkins or Elasticsearch often take 45–120 seconds to fully bind to their ports.
  • Resource Contention: On a small $5/month VPS with limited CPU, services start significantly slower than on a local dev machine.
  • The 'Silent Crash': The service tried to start, failed due to a typo in a config file, and exited. Since the process isn't running, the port never opens.

Proven Strategies to Fix the Timeout

1. Bump the Timeout for Heavy Workloads

If your service is healthy but slow, extend the window. For massive applications like GitLab or complex Kubernetes-managed pods, a 300-second (5-minute) timeout is a safer bet than the default.

- name: Wait for slow-starting legacy app
  wait_for:
    port: 8080
    timeout: 300

2. Use 'delay' to Reduce Log Noise

Spamming a port with connection attempts the exact millisecond after a systemd start command is inefficient. It can even fill up service logs with connection reset errors. Setting a delay: 15 tells Ansible to wait 15 seconds before making its first attempt.

- name: Start app and wait
  service:
    name: my_custom_app
    state: started

- name: Wait for port 8443
  wait_for:
    port: 8443
    delay: 15
    timeout: 120

3. Verify the Process Status First

Don't wait for a port if the service itself has already crashed. You can register the result of your service start task to see if it actually stayed running.

- name: Start PostgreSQL
  service:
    name: postgresql
    state: started
  register: pg_start_result

- name: Fail fast if service isn't even running
  fail:
    msg: "Postgres failed to start!"
  when: pg_start_result.state != 'started'

- name: Wait for Postgres port
  wait_for:
    port: 5432
    timeout: 60

4. Check Your Network Bindings

Is your service listening where you think it is? If your app is configured to bind only to the private IP 10.0.0.5, but your Ansible task is checking 127.0.0.1, it will always timeout. Run this command on the target server to verify the actual listening address:

ss -tulpn | grep :3306

If the output shows 0.0.0.0:3306, it's listening on all interfaces. If it shows a specific IP, make sure your host: parameter in Ansible matches that IP exactly.

How to Confirm the Fix

Run your playbook with the -v flag to see the module's internal timing. This helps you understand how close you are to the limit.

ansible-playbook site.yml -v

A successful run looks like this:

ok: [db_server] => {
    "changed": false,
    "elapsed": 22,
    "port": 3306,
    "state": "started"
}

In this scenario, "elapsed": 22 shows the service took 22 seconds to wake up. Since that's close to the 30-second default, you should probably set your timeout to 60 to allow for future spikes in disk I/O or CPU load.

Watch Out For These Gotchas

  • External Firewalls: If Ansible is running from a control node and checking a remote port, ensure your AWS Security Group or hardware firewall isn't blocking the traffic.
  • Localhost Ambiguity: On some systems, localhost resolves to ::1 (IPv6). If your service only listens on 127.0.0.1 (IPv4), use the explicit IP address instead of the hostname.

Related Error Notes