AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Facts: Gather, Use, and Create Custom Facts (Complete Guide)

By Luca Berton · Published 2024-01-01 · Category: installation

How to use Ansible facts to gather system information. ansible_facts, setup module, custom facts, fact caching.

Ansible Facts: Gather, Use, and Create Custom Facts (Complete Guide)

Ansible facts are system information automatically gathered from managed hosts — OS, IP addresses, hostname, memory, disk, network interfaces, and more. They're available as variables in your playbooks.

See also: Ansible gather_facts & ansible_facts: Access Host Information (Guide)

How Facts Work

When a playbook runs, Ansible calls the setup module on each host to collect facts before executing tasks.

- hosts: all
  # gather_facts: true  (default)
  tasks:
    - name: Show OS
      ansible.builtin.debug:
        msg: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
    # Output: "Ubuntu 24.04"

Common Facts Reference

System Information

ansible_hostname          # short hostname (e.g., "web01")
ansible_fqdn              # fully qualified domain name
ansible_distribution      # "Ubuntu", "CentOS", "Debian"
ansible_distribution_version  # "24.04"
ansible_distribution_major_version  # "24"
ansible_os_family         # "Debian", "RedHat", "Suse"
ansible_kernel            # "6.8.0-45-generic"
ansible_architecture      # "x86_64"
ansible_system            # "Linux"
ansible_machine           # "x86_64"

Network

ansible_default_ipv4.address    # primary IPv4 address
ansible_default_ipv4.interface  # "eth0"
ansible_default_ipv4.gateway    # default gateway
ansible_all_ipv4_addresses      # list of all IPv4 addresses
ansible_all_ipv6_addresses      # list of all IPv6 addresses
ansible_dns.nameservers         # DNS servers
ansible_domain                  # domain name

Memory and CPU

ansible_memtotal_mb       # total RAM in MB
ansible_memfree_mb        # free RAM in MB
ansible_processor_cores   # CPU cores per socket
ansible_processor_count   # number of CPU sockets
ansible_processor_vcpus   # total virtual CPUs

Disk

ansible_mounts             # list of mounted filesystems
ansible_devices            # block devices

Date and Time

ansible_date_time.date     # "2026-05-02"
ansible_date_time.time     # "14:30:00"
ansible_date_time.tz       # "UTC"
ansible_date_time.epoch    # Unix timestamp

See also: ansible.builtin.set_fact Module: Set Variables Dynamically (Complete Guide)

Access Facts

New Style (ansible_facts dictionary)

- ansible.builtin.debug:
    msg: "{{ ansible_facts['distribution'] }}"

- ansible.builtin.debug: msg: "{{ ansible_facts['default_ipv4']['address'] }}"

Classic Style (flat variables)

- ansible.builtin.debug:
    msg: "{{ ansible_distribution }}"

- ansible.builtin.debug: msg: "{{ ansible_default_ipv4.address }}"

Both styles work. The ansible_facts dictionary is the modern approach.

View All Facts

# Gather and display all facts for a host
ansible webserver01 -m ansible.builtin.setup

# Filter specific facts ansible webserver01 -m ansible.builtin.setup -a "filter=ansible_distribution*"

# Filter network facts ansible webserver01 -m ansible.builtin.setup -a "filter=ansible_default_ipv4"

# In a playbook
- name: Show all facts
  ansible.builtin.debug:
    var: ansible_facts

See also: Ansible facts: Gather, Use, and Create Custom Facts

Use Facts in Conditionals

- name: Install on Debian-based systems
  ansible.builtin.apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Install on RedHat-based systems ansible.builtin.dnf: name: nginx state: present when: ansible_os_family == "RedHat"

- name: Configure swap if memory < 2GB ansible.builtin.command: fallocate -l 2G /swapfile when: ansible_memtotal_mb < 2048

Use Facts in Templates

{# nginx.conf.j2 #}
worker_processes {{ ansible_processor_vcpus }};

server { listen 80; server_name {{ ansible_fqdn }}; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host {{ ansible_hostname }}; proxy_set_header X-Real-IP {{ ansible_default_ipv4.address }}; } }

Custom Facts (Local Facts)

Create custom facts by placing .fact files on managed hosts.

JSON Custom Fact

// /etc/ansible/facts.d/app.fact
{
    "name": "mywebapp",
    "version": "2.1.0",
    "environment": "production"
}

INI Custom Fact

; /etc/ansible/facts.d/app.fact
[app]
name=mywebapp
version=2.1.0
environment=production

Executable Custom Fact

#!/bin/bash
# /etc/ansible/facts.d/app.fact (must be executable)
echo '{"name": "mywebapp", "version": "'$(cat /opt/myapp/VERSION)'"}'

Deploy and Use Custom Facts

- name: Deploy custom fact
  ansible.builtin.copy:
    content: |
      {
        "version": "{{ app_version }}",
        "deployed_at": "{{ ansible_date_time.iso8601 }}"
      }
    dest: /etc/ansible/facts.d/deployment.fact
    mode: '0644'

- name: Re-read facts ansible.builtin.setup: filter: ansible_local

- name: Use custom fact ansible.builtin.debug: msg: "App version: {{ ansible_local.deployment.version }}"

Disable Fact Gathering

# Skip fact gathering for faster execution
- hosts: webservers
  gather_facts: false
  tasks:
    - name: Quick task (no facts needed)
      ansible.builtin.command: uptime

# Gather specific subsets only - hosts: webservers gather_facts: true gather_subset: - network - hardware

Fact Caching

Cache facts to avoid re-gathering on every run.

# ansible.cfg
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 86400  # 24 hours
# Redis caching
[defaults]
fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_timeout = 86400

FAQ

What are Ansible facts?

Ansible facts are system information automatically gathered from managed hosts — OS, IP addresses, hostname, CPU, memory, disk mounts, and network interfaces. They're available as variables in playbooks and templates.

How do I see all Ansible facts for a host?

Run ansible hostname -m ansible.builtin.setup to display all facts. Use -a "filter=ansible_distribution*" to filter specific facts. In a playbook, use debug: var=ansible_facts.

How do I get the hostname in Ansible?

Use ansible_hostname for the short hostname or ansible_fqdn for the fully qualified domain name. For the inventory hostname, use inventory_hostname.

What is the difference between ansible_hostname and inventory_hostname?

ansible_hostname is the actual system hostname gathered from the host. inventory_hostname is the name defined in your inventory file. They may differ if the inventory uses IPs or aliases.

How do I create custom Ansible facts?

Place .fact files (JSON, INI, or executable scripts) in /etc/ansible/facts.d/ on the managed host. Access them via ansible_local.filename.key. Use the setup module with filter=ansible_local to read them.

Can I disable fact gathering?

Yes, set gather_facts: false in your play. This speeds up execution when facts aren't needed. You can also use gather_subset to collect only specific fact categories.

Conclusion

Facts give your playbooks runtime awareness of each host's configuration. Use them for conditionals, templates, and dynamic configuration. Create custom facts for application-specific metadata and enable fact caching for performance.

Related Articles

Ansible Magic Variables: Special Variables ReferenceAnsible Variables: Complete GuideAnsible Hostname vs Inventory Hostname

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home