// learn Β· linux Β· rhce Β· 10 min

Ansible control node & inventory.

Ansible is agentless β€” one control node pushes Python modules to a whole fleet over SSH, with nothing to install on the targets. Watch the model go from `dnf install ansible-core` to a live ad-hoc command fanning out across grouped hosts.

Ansible control node and inventory animated tutorial. Agentless push architecture over SSH, installing ansible-core, writing INI and YAML inventories, host ranges, groups and group_vars, testing connectivity with the ping module, ad-hoc commands with -m and -a, privilege escalation, and project defaults in ansible.cfg. RHCE EX294 ready.
// ansible Β· control node & inventory

Ansible is agentless: one control node pushes work to a fleet over SSH. Watch the model go from install β†’ inventory β†’ groups β†’ a live ad-hoc command fanning out across hosts.

// before you start
you should know
  • Β·Comfortable with SSH and SSH key auth
  • Β·Basic Linux shell + package management (dnf)
  • Β·Know what YAML looks like (helps, not required)
by the end you'll

Install Ansible on a control node, write an inventory with groups, prove connectivity with the ping module, and run ad-hoc commands across a fleet.

pace: 10 minutes

ansible β€” step 1 / 6 Β· the model
πŸ›°οΈ control Β· ansible-corepushes over ssh β†’
πŸ›°οΈ control node
β”‚ ssh + python β”‚
[webservers]
πŸ–₯️ serveraβ—‹ idle
πŸ–₯️ serverbβ—‹ idle
[dbservers]
πŸ–₯️ servercβ—‹ idle

Agentless push β€” how Ansible reaches a fleet

Ansible has no agent. The CONTROL NODE opens an SSH connection to each MANAGED NODE, copies a tiny Python module over, runs it, captures the result, and deletes it. Managed nodes need only an SSH server and Python β€” nothing to install, no daemon to keep alive. That's the whole architecture: push over SSH, run, clean up. Every module is written to be idempotent, so re-running a play changes nothing if the system already matches.

$dnf install ansible-core
$ansible --version
$ssh servera 'python3 --version'
// key insight

Everything in Ansible flows from one idea: the control node pushes Python over SSH and the managed nodes stay dumb. The inventory names the fleet, groups carve it into targets, the ping module proves the path, and ad-hoc commands let you act now β€” but the moment a task is worth repeating, it belongs in a playbook so it's idempotent and reviewable.

// exam-ready Β· control node, inventory & ad-hoc
$dnf install ansible-core
$ansible --version
$ansible all -m ping
$ansible all --list-hosts
$ansible GROUP --list-hosts
$ansible-inventory --graph
$ansible all -m setup
$ansible all -a "CMD"
$ansible H -m shell -a "a | b"
$ansible H -m dnf -a "name=X state=present" -b
$ansible H -m service -a "name=X state=started enabled=true" -b
$ansible H -m copy -a "src=… dest=…"
$-i inventory
$-u USER -b --become-user=root
$./ansible.cfg [defaults]
$ansible-config dump --only-changed
// check yourself
4 quick questions
Q1

What does a managed node need installed for Ansible to manage it?

Q2

`ansible all -m ping` returns SUCCESS β†’ pong. What did that actually prove?

Q3

You want to install httpd on the webservers group, just once, right now, as root. Best ad-hoc command?

Q4

You run Ansible from a project directory that has its own ./ansible.cfg, and /etc/ansible/ansible.cfg also exists. Which wins?

These aren't graded β€” they're just for active recall, which is what actually makes the lesson stick.

πŸ”‘
// the thing Ansible rides on

SSH key authentication

Ansible is only as smooth as your SSH. Set up key-based auth to every managed node and `ansible all -m ping` just works β€” no passwords, no prompts.

open β†’

Read this lesson as text6 chapters Β· quiz answers

  1. 01Agentless push β€” how Ansible reaches a fleet

    Ansible has no agent. The CONTROL NODE opens an SSH connection to each MANAGED NODE, copies a tiny Python module over, runs it, captures the result, and deletes it. Managed nodes need only an SSH server and Python β€” nothing to install, no daemon to keep alive. That's the whole architecture: push over SSH, run, clean up. Every module is written to be idempotent, so re-running a play changes nothing if the system already matches.

    • $ dnf install ansible-core β€” install on the CONTROL node only
    • $ ansible --version β€” confirm + see config path used
    • $ ssh servera 'python3 --version' β€” managed node just needs ssh + python
  2. 02The inventory β€” who you manage

    An inventory lists the managed hosts. The default is /etc/ansible/hosts, but real projects keep a project-local file and pass it with -i inventory. It can be INI or YAML. Hosts are names or IPs; ranges collapse repetition β€” server[a:c] expands to servera, serverb, serverc. Two groups always exist implicitly: all (every host) and ungrouped (hosts in no group).

    • $ [webservers]\nserver[a:b].lab.example.com β€” INI: a group + a host range
    • $ ansible all --list-hosts -i inventory β€” what does Ansible think exists?
    • $ ansible-inventory -i inventory --graph β€” tree of groups β†’ hosts
  3. 03Groups & group_vars β€” organise the fleet

    Group hosts by role, location, or stage β€” a host can belong to many groups at once. Nest groups with [parent:children] in INI (or children: in YAML) so all β†’ production β†’ webservers cascades. Variables that apply to a whole group live in group_vars/GROUPNAME (and per-host overrides in host_vars/HOST). Ansible loads them automatically β€” no -e needed.

    • $ ansible webservers --list-hosts β€” resolve a group to its hosts
    • $ group_vars/webservers.yml β€” vars auto-applied to the group
    • $ host_vars/servera.yml β€” per-host overrides win over group
  4. 04Test connectivity β€” the ping module

    ansible all -m ping is the first thing you run. It is NOT an ICMP ping β€” the ping module logs in over SSH, runs Python on the far side, and replies pong only if the whole path works. A green SUCCESS β†’ pong proves SSH auth, Python, and (if used) privilege escalation are all healthy. Connection details come from vars: ansible_host, ansible_user, and --become/-b for sudo.

    • $ ansible all -m ping β€” SSH + Python reachability, not ICMP
    • $ ansible all -m ping -u devops -b β€” as user devops, escalate with sudo
    • $ ansible all -m setup β€” dump all gathered facts about a host
  5. 05Ad-hoc commands β€” one-off tasks, no playbook

    For a quick, one-shot action you don't need a playbook β€” ansible GROUP -m MODULE -a "ARGS". The default module is command (so -a "uptime" just runs uptime). Use shell when you need pipes or redirects. Add -b to escalate. Ad-hoc shines for checks and emergencies; anything you'll repeat belongs in a playbook so it's idempotent and reviewable.

    • $ ansible all -a "uptime" β€” command module is the default
    • $ ansible webservers -m dnf -a "name=httpd state=present" -b β€” install a package, as root
    • $ ansible all -m service -a "name=firewalld state=started enabled=true" -b β€” start + enable
  6. 06ansible.cfg β€” stop repeating yourself

    Typing -i inventory -u devops -b every time gets old. A project-local ansible.cfg sets those defaults. Precedence (first wins): ANSIBLE_CONFIG env var β†’ ./ansible.cfg in the current dir β†’ ~/.ansible.cfg β†’ /etc/ansible/ansible.cfg. The project-local file is the convention β€” keep it beside your playbooks so the whole team gets the same inventory, remote_user, and become behaviour for free.

    • $ [defaults]\ninventory = ./inventory\nremote_user = devops β€” no more -i / -u flags
    • $ [privilege_escalation]\nbecome = true β€” escalate by default
    • $ ansible-config dump --only-changed β€” what did my cfg actually override?

Quiz β€” answers

What does a managed node need installed for Ansible to manage it?
β†’Only an SSH server and Python β€” Ansible is agentless and pushes modules over SSH, runs them, then removes them.Ansible's defining feature is that it's agentless. The control node copies a small Python module over SSH, executes it on the target, and cleans up. Nothing persistent runs on managed nodes.
ansible all -m ping returns SUCCESS β†’ pong. What did that actually prove?
β†’SSH login worked, Python ran on the far side, and the result came back β€” the full management path is healthy. It is not an ICMP ping.The ping module is a connectivity test for the whole Ansible path: SSH transport + Python execution (+ privilege escalation if you pass -b). A normal ICMP ping would tell you none of that.
You want to install httpd on the webservers group, just once, right now, as root. Best ad-hoc command?
β†’ansible webservers -m dnf -a "name=httpd state=present" -bUse the dnf module (idempotent) with -b to escalate. The bare -a "dnf install httpd" runs the command module, which isn't idempotent and won't escalate without -b. There's no host called 'webservers' for plain ssh.
You run Ansible from a project directory that has its own ./ansible.cfg, and /etc/ansible/ansible.cfg also exists. Which wins?
β†’The project-local ./ansible.cfg wins β€” precedence is ANSIBLE_CONFIG env β†’ ./ansible.cfg β†’ ~/.ansible.cfg β†’ /etc/ansible/ansible.cfg.The first match in that order is used wholesale (configs don't merge). A project-local ansible.cfg is the convention precisely because it overrides the system file for everyone working in that directory.
// more in systems

keep going β€” these pair well with what you just learned.

see all systems β†’

See also

back to RHCSA / RHCE trackall lessons