Part 37 — Facts¶
Chapter status: outline
This chapter is scoped but not yet written in full prose. The sections below define what each part will cover.
Every play, by default, starts by asking each host a question: "what are you?" This chapter covers the answer — facts — from a usage standpoint. The internals of how the answer is gathered are covered separately in Volume 3.
Why This Exists¶
- Facts are the lowest-effort source of real, live host data a playbook can use — no inventory maintenance required — and nearly every conditional or template in a real playbook eventually reads one. This chapter existed only as a forward-reference from Part 9 — Variables and Precedence until now; it closes that gap.
Problem Statement¶
- Beginners either don't know facts exist (and hardcode values a fact would have given them for free) or over-rely on them (gathering facts on every run of every play, even when nothing in the play actually reads one, adding needless latency).
Internal Architecture¶
- Facts are gathered by an implicit run of the
ansible.builtin.setupmodule at the start of a play, unlessgather_facts: falseis set — full mechanical trace of this in Volume 3, Part 16. - Gathered data lands in the
ansible_factsnamespace (and, for backward compatibility, as flattened top-levelansible_*variables) — both forms are shown side by side.
Step-by-Step Explanation¶
gather_facts:true(default),falseto skip entirely, orsmartat the play level to skip if facts were already gathered this run.gather_subset: narrowing whatsetupcollects (all,min,network,hardware,virtual,!allexclusions) to cut gathering time on large fleets.- Common facts used in real playbooks:
ansible_distribution/ansible_distribution_version(OS branching),ansible_default_ipv4,ansible_memtotal_mb,ansible_hostnamevs.inventory_hostname. - Custom facts:
.factfiles or executable scripts under/etc/ansible/facts.d/on the managed node, surfaced automatically underansible_local. set_fact: defining a fact-like variable at runtime from within a play, and how its precedence differs from a gathered fact (cross-reference to the Part 9 pyramid).- Fact caching: backing
gather_factswith a cache plugin (Redis, JSON file, Memcached) so repeated runs against the same host don't re-gather every time — previewed here, quantified in Volume 6, Part 32.
Production Best Practices¶
- Setting
gather_subsetto only what a play actually reads, instead of gathering everything by default, once a play's real dependencies are known. - Using fact caching for any inventory large enough that fact-gathering latency is a measurable fraction of total run time.
Common Mistakes¶
- Assuming
ansible_hostnameandinventory_hostnameare always the same value — they diverge whenever a host's real hostname doesn't match its inventory name. - Reading a fact inside a
when:before confirminggather_factswasn't disabled for that play, and getting a confusing "undefined variable" error instead of a clear fact-related one. - Re-gathering facts on every play in a multi-play book when nothing changed on the host between plays.
Performance Considerations¶
- Fact gathering is a real remote execution step with real cost (Volume 3, Part 16) —
gather_subsetscoping and fact caching are the two levers that matter, fully quantified in Volume 6.
Security Considerations¶
setupoutput can include sensitive-adjacent data (network configuration, mounted filesystems); treat verbose (-vvv) output containing facts with the same log-handling care as any other host data.
Interview Questions¶
- "What triggers Ansible's implicit fact-gathering step, and how would you disable or scope it?"
- "What's the difference between a gathered fact and a variable set with
set_fact?" - "How would you speed up fact gathering across a fleet of a thousand hosts?"
Hands-On Lab¶
- Run
ansible all -m setupagainst a test host and findansible_distributionandansible_default_ipv4.addressin the output; then write a one-task playbook that prints a different message depending onansible_distributionusingwhen:.
Summary¶
- Facts are auto-discovered host data gathered by the
setupmodule at the start of a play — usable directly, cacheable for performance, and extensible via custom facts — and they follow the same precedence rules as any other variable once gathered.
Next¶
Continue to Part 10 — ansible.cfg.