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

VariableMeaningSample Value
ansible_hostnameShort host nameweb1
ansible_distributionOperating system nameUbuntu
ansible_distribution_versionRelease number22.04
ansible_os_familyLinux familyDebian
ansible_memtotal_mbTotal memory in megabytes7961
ansible_processor_vcpusVirtual CPU count4
ansible_default_ipv4.addressMain IP address10.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.

VariablePurpose
inventory_hostnameName of the current host as written in inventory
groupsDictionary of all groups and their hosts
group_namesGroups that contain the current host
hostvarsVariables and facts of every host
play_hostsHosts active in the current play
ansible_check_modeTrue 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.