Special Magic Variables
A handful of variables are always available in every playbook, without you ever defining them — Ansible populates them automatically with information about the current run itself: which host is currently executing, what groups it belongs to, and even what every other host in your inventory looks like. This chapter covers the four most useful ones.
inventory_hostname — The Current Host’s Own Name
inventory_hostname holds the name Ansible uses to refer to whichever host is currently running the task — the same string you used as its key in your inventory file:
- name: Print my own inventory name
hosts: servers
tasks:
- name: Show it
ansible.builtin.debug:
msg: "I am {{ inventory_hostname }}"ok: [ubuntu] => {
"msg": "I am ubuntu"
}
ok: [fedora] => {
"msg": "I am fedora"
}Worth distinguishing from ansible_facts['hostname'], covered in the facts chapter — that’s the operating system’s own reported hostname, which could genuinely differ from the alias you chose in your inventory. inventory_hostname is always the inventory-side name specifically.
group_names — Which Groups The Current Host Belongs To
A list of every group the current host is a member of:
- name: Print my groups
ansible.builtin.debug:
msg: "I belong to: {{ group_names | join(', ') }}"ok: [ubuntu] => {
"msg": "I belong to: servers"
}That join filter is the same one from the Jinja2 chapter, put to real use here — group_names is a list, and join turns it into a readable sentence.
hostvars — Peeking At Another Host’s Variables
hostvars is a dictionary of every host’s variables, indexed by hostname — letting a task running on one host look up data belonging to a completely different one:
- name: Hostvars Demo
hosts: ubuntu
tasks:
- name: Print fedora's address from a task running on ubuntu
ansible.builtin.debug:
msg: "Fedora's address is {{ hostvars['fedora']['ansible_host'] }}"ok: [ubuntu] => {
"msg": "Fedora's address is 10.0.0.2"
}This play only targets ubuntu — and yet it reached straight into fedora’s data. This is genuinely useful whenever one host needs to know about another: a load balancer’s configuration referencing the addresses of the backend servers it points to, for instance.
ansible_play_hosts — Every Host In This Play
A list of every host actually participating in the current play:
- name: Print all hosts in this play
ansible.builtin.debug:
msg: "This play includes: {{ ansible_play_hosts | join(', ') }}"Useful for summary or reporting-style tasks that want to reference the whole set of hosts being acted on, rather than just the one currently running.
A Gotcha: hostvars Needs Facts Gathered First
hostvars gives you access to variables for any host in your inventory, not just ones targeted by the current play — but there’s a real limit specifically around facts. Inventory-sourced data (like ansible_host, or anything from a host_vars file) is available regardless, since that comes from static configuration.
Fact-derived data is only available for a host once that host has actually had its facts gathered at some point during the current run. Reference hostvars['some_host']['ansible_distribution'] for a host that was never targeted by any play so far in this execution, and you’ll hit an undefined-variable error — the fact simply was never collected for it.
Best Practices
- Use
inventory_hostnamefor the current host’s own inventory name, and keep it clearly distinct in your head fromansible_facts['hostname'], which is a different piece of information entirely. - Use
hostvarsfor genuine cross-host references, but keep in mind fact-derived fields only exist for hosts already processed in this run — inventory-sourced fields are always safe to reference regardless. - Reach for
ansible_play_hostsfor summary or reporting tasks that need to describe the whole set of hosts in a play, rather than manually maintaining a separate list yourself.