What's Actually Happening

Ansible playbook execution times out when tasks take longer than the configured timeout. Long-running commands, slow network connections, or unresponsive hosts cause playbook failures.

The Error You'll See

Task timeout:

```bash $ ansible-playbook site.yml

TASK [Install packages] ************ fatal: [server1]: FAILED! => { "msg": "Command timed out after 30 seconds" } ```

SSH timeout:

bash
TASK [Gather Facts] ***********************************************************
fatal: [server1]: UNREACHABLE! => {
    "msg": "Failed to connect to the host via ssh: Connection timed out",
    "unreachable": true
}

Async task timeout:

bash
TASK [Long running task] *******************************************************
fatal: [server1]: FAILED! => {
    "msg": "async task timed out after 3600 seconds"
}

Why This Happens

  1. 1.Long-running commands - Tasks exceed default timeout
  2. 2.Slow network - High latency or low bandwidth
  3. 3.SSH connection issues - Network unreachable or firewall
  4. 4.Heavy operations - Large file transfers or package installs
  5. 5.Unresponsive hosts - Target system frozen
  6. 6.Wrong timeout value - Insufficient for operation

Step 1: Identify Timed Out Tasks

```bash # Run with verbose output ansible-playbook site.yml -v

# Run with more verbosity ansible-playbook site.yml -vvv

# Check specific host ansible-playbook site.yml -l server1 -vvv

# Check task details in output: # "timeout": 30 <- default timeout

# Common timeout-prone tasks: # - package installation (yum, apt) # - large file copy # - database operations # - system updates # - template rendering with large files

# Run single task for testing ansible server1 -m shell -a "long-running-command" -B 3600 ```

Step 2: Increase Task Timeout

```yaml # Increase timeout for specific task - name: Install packages ansible.builtin.yum: name: "*" state: latest async: 3600 # Maximum runtime in seconds poll: 60 # Check every 60 seconds # async: 3600, poll: 0 = fire and forget

# Or use timeout for commands - name: Long running command ansible.builtin.command: cmd: /usr/bin/long-operation timeout: 600 # 10 minutes (Ansible 2.10+)

# For shell module - name: Shell command with timeout ansible.builtin.shell: cmd: /usr/bin/slow-command timeout: 300

# In ansible.cfg [defaults] timeout = 30 # SSH timeout (default) task_timeout = 600 # Task timeout (default: 0 = no limit) ```

Step 3: Increase SSH Timeout

```bash # In ansible.cfg [defaults] timeout = 60 # SSH connection timeout (default 10)

[ssh_connection] ssh_args = -o ConnectTimeout=60 -o ServerAliveInterval=30 pipelining = True

# Or via environment variable export ANSIBLE_TIMEOUT=60

# Or in playbook: - name: Play with custom timeout hosts: all gather_facts: yes vars: ansible_timeout: 60

# Check SSH connection ansible all -m ping -e "ansible_timeout=60"

# Test SSH directly ssh -o ConnectTimeout=60 user@server1 ```

Step 4: Use Async for Long Tasks

```yaml # For long-running tasks, use async

  • name: Run long operation
  • ansible.builtin.command:
  • cmd: /usr/bin/long-operation
  • async: 3600 # 1 hour maximum
  • poll: 0 # Don't wait, run asynchronously
  • register: long_task
  • name: Check on async task
  • ansible.builtin.async_status:
  • jid: "{{ long_task.ansible_job_id }}"
  • register: job_result
  • until: job_result.finished
  • retries: 60
  • delay: 60 # Check every minute for 1 hour

# For fire-and-forget: - name: Start background process ansible.builtin.command: cmd: /usr/bin/background-service async: 45 poll: 0

# For multiple async tasks: - name: Run multiple tasks async ansible.builtin.command: "{{ item }}" async: 3600 poll: 0 loop: - /usr/bin/task1 - /usr/bin/task2 register: async_tasks

  • name: Wait for all tasks
  • ansible.builtin.async_status:
  • jid: "{{ item.ansible_job_id }}"
  • register: job_result
  • until: job_result.finished
  • retries: 60
  • delay: 60
  • loop: "{{ async_tasks.results }}"
  • `

Step 5: Optimize Package Installation

```yaml # Package installation can timeout on slow connections

# WRONG: Update all packages (slow) - name: Update all packages ansible.builtin.yum: name: "*" state: latest # This can take a long time

# BETTER: Update specific packages - name: Update specific packages ansible.builtin.yum: name: - nginx - openssl state: latest async: 1800 poll: 30

# Use cache update separately - name: Update cache ansible.builtin.apt: update_cache: yes async: 600 poll: 30

  • name: Install packages
  • ansible.builtin.apt:
  • name: nginx
  • state: present

# Disable GPG check if causing timeout - name: Install package without GPG check ansible.builtin.yum: name: package-name state: present disable_gpg_check: yes ```

Step 6: Optimize File Transfers

```yaml # Large file transfers can timeout

# Use synchronize (rsync) for large files - name: Sync large directory ansible.posix.synchronize: src: /local/path/ dest: /remote/path/ # Uses rsync, more efficient than copy

# For single large file with timeout - name: Copy large file ansible.builtin.copy: src: large_file.tar.gz dest: /tmp/large_file.tar.gz async: 3600 poll: 60

# Use unarchive for archives - name: Extract archive ansible.builtin.unarchive: src: large_file.tar.gz dest: /opt/ remote_src: no async: 1800 poll: 30

# Fetch large files - name: Fetch large file ansible.builtin.fetch: src: /remote/large_file.log dest: /local/backup/ flat: yes async: 1800 poll: 30 ```

Step 7: Fix Network Connectivity

```bash # Check if host is reachable ansible server1 -m ping

# Test SSH connection ssh -v user@server1

# Check network latency ping -c 5 server1

# Check for packet loss mtr server1

# In ansible.cfg, adjust SSH settings [ssh_connection] ssh_args = -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=3 # ServerAliveInterval: Send keepalive every 15 seconds # ServerAliveCountMax: Disconnect after 3 missed keepalives

# Use ControlPersist for faster reconnection ssh_args = -o ControlMaster=auto -o ControlPersist=60s

# Increase pipelining for performance pipelining = True ```

Step 8: Handle Unreachable Hosts

```yaml # Handle unreachable hosts gracefully

  • name: Task that may timeout
  • ansible.builtin.command:
  • cmd: /usr/bin/some-command
  • timeout: 60
  • ignore_unreachable: yes
  • ignore_errors: yes
  • register: result
  • name: Handle unreachable
  • ansible.builtin.debug:
  • msg: "Host was unreachable"
  • when: result.unreachable is defined and result.unreachable

# Block with rescue for timeout handling - name: Block with error handling block: - name: Potentially slow task ansible.builtin.command: cmd: /usr/bin/slow-command timeout: 300 rescue: - name: Handle timeout ansible.builtin.debug: msg: "Task timed out, running fallback" - name: Fallback action ansible.builtin.command: cmd: /usr/bin/fallback ```

Step 9: Use Strategies for Timeout Control

```yaml # Use free strategy to not wait for all hosts - name: Run without waiting hosts: all strategy: free # Don't wait for other hosts tasks: - name: Long task ansible.builtin.command: cmd: /usr/bin/long-command async: 3600 poll: 60

# Use linear strategy (default) with batch - name: Batch execution hosts: all strategy: linear serial: 5 # Run on 5 hosts at a time tasks: - name: Task ansible.builtin.command: cmd: /usr/bin/command

# Debug strategy for troubleshooting - name: Debug execution hosts: all strategy: debug # Pauses on failure for interactive debugging ```

Step 10: Monitor Long-Running Playbooks

```bash # Use callback plugins for monitoring

# In ansible.cfg [defaults] callbacks_enabled = profile_tasks, timer

# profile_tasks shows task timing # timer shows overall playbook time

# Run with timing ansible-playbook site.yml

# Output shows: # TASK [Install packages] *********** # Wednesday 16 April 2026 00:37:00 +0000 (0:00:30.123) 0:01:15.456 **** # ^ task duration ^ total time

# Check running processes ansible all -m shell -a "ps aux | grep ansible"

# Monitor async tasks ansible all -m async_status -a "jid=<job_id>" ```

Ansible Timeout Settings Reference

SettingLocationDefaultPurpose
timeoutansible.cfg10SSH connection timeout
task_timeoutansible.cfg0Task execution timeout
asynctask-Maximum async runtime
polltask10Async status check interval
timeout (task)task-Command timeout (2.10+)

Verify the Fix

```bash # After increasing timeouts or optimizing tasks

# 1. Run playbook with verbose output ansible-playbook site.yml -v

# 2. Check task timing with profile_tasks ansible-playbook site.yml # Should show task durations

# 3. Verify no timeout errors # Playbook should complete successfully

# 4. Check async tasks completed ansible all -m async_status -a "jid=<job_id>" # Should show finished: true

# 5. Test connectivity ansible all -m ping # All hosts should respond

# 6. Monitor future runs ansible-playbook site.yml --check # Dry run to verify timing ```

  • [Fix Ansible Host Unreachable](/articles/fix-ansible-host-unreachable)
  • [Fix Ansible Task Failed](/articles/fix-ansible-task-failed)
  • [Fix Ansible SSH Connection Failed](/articles/fix-ansible-ssh-connection-failed)