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 Reference • Ansible Variables: Complete Guide • Ansible Hostname vs Inventory HostnameCategory: installation