Devops

Running Ansible Playbooks Against Remote Hosts Without Surprises

April 7, 2026
Published
#Ansible#Automation#Configuration Management#DevOps#Infrastructure#SSH

Most developers discover Ansible with a simple localhost example. It works, it’s clean, and everything feels predictable. Then comes the real task: running playbooks against remote hosts. That’s where things can either feel magical… or frustrating.

Let’s walk through how Ansible actually interacts with remote machines, how to set it up correctly, and what tends to break in real environments.

What “Remote Hosts” Really Means in Ansible

Ansible doesn’t require agents on remote machines. Instead, it connects over SSH (or WinRM for Windows). When you run a playbook, Ansible:

  • Reads your inventory
  • Connects to each host via SSH
  • Executes tasks using temporary modules
  • Returns results

This agentless model is simple, but it also means your SSH setup must be correct.

A Minimal Working Example

Let’s start with a basic inventory and playbook.

Inventory file (hosts.ini)

TEXT
1[web]
2192.168.1.10
3192.168.1.11
4
5[db]
6192.168.1.20
7

Playbook (setup.yml)

YAML
1- name: Configure web servers
2  hosts: web
3  become: true
4
5  tasks:
6    - name: Install nginx
7      apt:
8        name: nginx
9        state: present
10        update_cache: yes
11

Run it with:

TEXT
1ansible-playbook -i hosts.ini setup.yml

If SSH access works, Ansible handles the rest.

SSH Configuration: Where Most Issues Start

A common mistake developers make is assuming Ansible manages authentication. It doesn’t. It relies entirely on your SSH setup.

You should aim for passwordless SSH:

TEXT
1ssh-copy-id user@192.168.1.10

Then test manually:

TEXT
1ssh user@192.168.1.10

If this fails, Ansible will fail too.

Defining SSH details in inventory

You can specify connection details per host:

TEXT
1192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa

Or group-wide:

TEXT
1[web:vars]
2ansible_user=ubuntu
3ansible_ssh_private_key_file=~/.ssh/id_rsa

Privilege Escalation (become)

Most remote tasks require elevated privileges. That’s where become comes in.

Instead of logging in as root, you typically:

  • Connect as a normal user
  • Escalate privileges using sudo
YAML
1- hosts: web
2  become: true
3

If sudo requires a password, you can pass it with:

TEXT
1ansible-playbook setup.yml --ask-become-pass

Inventory Isn’t Just a List of IPs

Inventory becomes powerful when you structure it logically.

Example:

TEXT
1[web]
2web1.example.com
3web2.example.com
4
5[db]
6db1.example.com
7
8[production:children]
9web
10db
11

This allows you to:

  • Target specific groups
  • Apply different configurations
  • Reuse playbooks across environments

You can then run:

TEXT
1ansible-playbook -i hosts.ini setup.yml --limit web

Ad-hoc Commands Before Full Playbooks

Before running a full playbook, it’s smart to test connectivity.

TEXT
1ansible all -i hosts.ini -m ping

If this fails, don’t bother debugging your playbook yet. Fix connectivity first.

Handling Different Environments

In real setups, you’ll have dev, staging, and production environments. Instead of duplicating playbooks, use separate inventory files:

TEXT
1inventory/
2  dev.ini
3  staging.ini
4  prod.ini
5

Run against a specific environment:

TEXT
1ansible-playbook -i inventory/prod.ini setup.yml

This keeps your automation consistent while adapting to different infrastructures.

Common Pitfalls (and How to Avoid Them)

1. SSH Works Manually but Not in Ansible

This often happens due to missing key configuration or incorrect user settings. Always define ansible_user explicitly if unsure.

2. Python Not Installed on Remote Hosts

Ansible requires Python on the target machine. Minimal OS images sometimes don’t include it.

Fix:

TEXT
1ansible all -i hosts.ini -m raw -a "apt-get update && apt-get install -y python3"

3. Permission Denied Errors

This is usually a sudo issue. Either:

  • Enable passwordless sudo
  • Use --ask-become-pass

4. Host Key Checking Problems

For automation environments, you may want to disable strict host checking:

TEXT
1export ANSIBLE_HOST_KEY_CHECKING=False

Use this carefully in production.

A Slightly More Realistic Example

Let’s configure both web and database servers in one playbook:

YAML
1- name: Setup web servers
2  hosts: web
3  become: true
4
5  tasks:
6    - name: Install nginx
7      apt:
8        name: nginx
9        state: present
10
11- name: Setup database servers
12  hosts: db
13  become: true
14
15  tasks:
16    - name: Install PostgreSQL
17      apt:
18        name: postgresql
19        state: present
20

Here’s where Ansible shines: one command, multiple systems, consistent results.

Performance Considerations

By default, Ansible runs tasks in parallel across hosts. You can control this using the forks setting:

TEXT
1ansible-playbook setup.yml -f 10

Higher values speed up execution but can overload your control machine or network.

Why This Approach Works Well in DevOps

Running Ansible playbooks against remote hosts gives you:

  • Centralized control
  • No agent maintenance
  • Easy scaling across environments
  • Repeatable infrastructure changes

It’s especially effective for provisioning servers, patching systems, and enforcing configuration consistency.

Closing Thought

Once your SSH and inventory are solid, Ansible becomes predictable. Most “Ansible problems” aren’t really Ansible problems—they’re environment or access issues.

Get connectivity right first, keep your inventory clean, and your playbooks will behave exactly the way you expect.

Comments

Leave a comment on this article with your name, email, and message.

Loading comments...

Similar Articles

More posts from the same category you may want to read next.

Share: