Ansible Facts and Magic Variables
Before a play runs its tasks, Ansible asks every managed node to describe itself. Each node reports its operating system, memory, disks, network addresses, and more. These details are called facts. Facts work like a passport: the document tells border officers who the traveler is without any questions. Playbooks read facts to make decisions, such as installing a different package on Ubuntu than on Red Hat.
How Fact Gathering Works
The setup module runs automatically at the start of each play and stores results in variables prefixed with ansible_.
Control Node Managed Nodes
┌──────────┐ 1. run setup ┌──────────┐
│ │──────────────────▶│ web1 │
│ Ansible │◀──────────────────│ facts │
│ │ 2. send facts └──────────┘
│ │──────────────────▶┌──────────┐
│ │◀──────────────────│ db1 │
└──────────┘ │ facts │
│ └──────────┘
▼
3. tasks use facts to decide
See the Facts
ansible web1 -m ansible.builtin.setup
ansible web1 -m ansible.builtin.setup -a "filter=ansible_distribution*"
The first command prints hundreds of values as JSON. The second narrows the output to distribution details.
Popular Facts
| Variable | Meaning | Sample Value |
|---|---|---|
| ansible_hostname | Short host name | web1 |
| ansible_distribution | Operating system name | Ubuntu |
| ansible_distribution_version | Release number | 22.04 |
| ansible_os_family | Linux family | Debian |
| ansible_memtotal_mb | Total memory in megabytes | 7961 |
| ansible_processor_vcpus | Virtual CPU count | 4 |
| ansible_default_ipv4.address | Main IP address | 10.0.1.15 |
Use Facts in a Playbook
- hosts: all
become: true
tasks:
- name: Install Apache on Debian family systems
ansible.builtin.apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: Install Apache on Red Hat family systems
ansible.builtin.dnf:
name: httpd
state: present
when: ansible_os_family == "RedHat"
- name: Report memory
ansible.builtin.debug:
msg: "{{ ansible_hostname }} has {{ ansible_memtotal_mb }} MB of RAM"
Speed Up or Skip Gathering
Fact collection costs time on large fleets. Turn it off when a play never reads facts.
- hosts: all
gather_facts: false
tasks:
- ansible.builtin.ping:
A play that needs only a few facts can limit the collection with gather_subset.
gather_facts: true
gather_subset:
- '!all'
- min
Custom Facts
Place a file ending in .fact inside /etc/ansible/facts.d/ on a managed node. The file may use INI or JSON format. Ansible loads the values under ansible_local.
# /etc/ansible/facts.d/app.fact
[general]
owner=payments-team
tier=gold
Playbooks read the result as {{ ansible_local.app.general.tier }}.
Create Facts During a Run
The set_fact module stores a calculated value for later tasks on the same host.
- ansible.builtin.set_fact:
low_memory: "{{ ansible_memtotal_mb < 2048 }}"
Magic Variables
Magic variables come from Ansible itself rather than from a node. Their names are reserved, and no one can override them.
| Variable | Purpose |
|---|---|
| inventory_hostname | Name of the current host as written in inventory |
| groups | Dictionary of all groups and their hosts |
| group_names | Groups that contain the current host |
| hostvars | Variables and facts of every host |
| play_hosts | Hosts active in the current play |
| ansible_check_mode | True during a dry run |
The hostvars variable lets one host read facts from another. A web server can look up the database server address with {{ hostvars['db1'].ansible_default_ipv4.address }}. The target host must have gathered facts earlier in the run.
Try This
Run the setup module with a filter for ansible_mem* against one host. Write a playbook that prints the host name, the operating system, and the total memory in one sentence. Rerun with gather_facts: false and read the error message, which confirms the playbook depends on facts.
Summary
Facts describe each managed node and arrive through the setup module at the start of a play. Playbooks use facts to choose packages, tune settings, and print reports. Custom facts add business details, and set_fact stores calculated values. Magic variables such as hostvars and groups expose inventory and cross-host information.
