LinuxXXXIV · Configuration ManagementInventory
Inventory and facts - knowing your fleet
What you'll learn
- Build a static inventory
- Use dynamic inventory for cloud and CMDB
- Gather and use host facts
- Group hosts by role
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
Ansible inventory is the list of hosts and groups. Facts are gathered host variables. Together they let playbooks target the right hosts with the right configuration.
Static inventory
# /etc/ansible/hosts
web01.example.com
web02.example.com
db01.example.com
[webservers]
web01.example.com
web02.example.com
[databases]
db01.example.com
[production:children]
webservers
databases
Inventory can be a file, a directory of files, or a dynamic source.
Dynamic inventory
For dynamic fleets (cloud, CMDB, LDAP), point -i at an
inventory plugin configuration instead of a static file. The
plugin queries the source at run time, so the inventory can never
be stale relative to what is actually deployed.
The configuration is YAML and lives in your repository:
# inventory/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- eu-west-1
filters:
instance-state-name: running
keyed_groups:
- key: tags.Role
prefix: role
- key: tags.Environment
prefix: env
ansible-playbook -i inventory/aws_ec2.yml site.yml
keyed_groups is the part that earns its keep. It turns instance
tags into Ansible groups, so role_webserver and env_prod
exist without anyone maintaining them. That is what makes
environment separation and wave-by-wave targeting possible on a
fleet that changes hourly — a hand-written file cannot keep up,
and the failure mode when it falls behind is a playbook that
skips the host nobody noticed was missing.
Always inspect the resolved inventory before you run anything against it:
ansible-inventory -i inventory/aws_ec2.yml --graph # group tree
ansible-inventory -i inventory/aws_ec2.yml --list # full hostvars
Other sources follow the same shape:
openstack.cloud.openstack, community.vmware.vmware_vm_inventory,
azure.azcollection.azure_rm. Run
ansible-doc -t inventory -l to list the plugins your installed
collections provide.
Group by role
Group hosts by role, environment, or any other dimension:
[webservers]
web[01:10].example.com
[webservers:vars]
nginx_worker_processes=4
[databases]
db[01:03].example.com
[production]
web[01:10].example.com
db[01:03].example.com
:vars sets group variables. [01:10] is a range (web01
through web10).
Facts
Gathered facts describe each host:
- hosts: all
tasks:
- debug:
var: ansible_facts
Common facts:
ansible_hostname: the host’s name.ansible_default_ipv4.address: primary IPv4 address.ansible_distribution: Linux distribution (Ubuntu, RHEL).ansible_distribution_version: version (22.04, 9.x).ansible_kernel: kernel version.ansible_memtotal_mb: total memory in MB.ansible_processor_count: number of CPU cores.
Use facts in playbooks
- hosts: webservers
tasks:
- name: Set worker processes based on CPU count
lineinfile:
path: /etc/nginx/nginx.conf
regexp: '^worker_processes'
line: "worker_processes {{ ansible_processor_count }};"
become: yes
Facts are templated with {{ ... }}.
Custom facts
Set custom variables for hosts or groups:
# group_vars/webservers.yml
nginx_listen_port: 80
nginx_worker_processes: 4
# host_vars/web01.example.com.yml
ansible_host: 10.0.0.10
Ansible loads group_vars/<group>.yml and
host_vars/<host>.yml automatically.
Conditional playbooks
Use facts to skip tasks:
- hosts: all
tasks:
- name: Install nginx on Debian
apt:
name: nginx
when: ansible_os_family == "Debian"
- name: Install nginx on Red Hat
dnf:
name: nginx
when: ansible_os_family == "RedHat"
Knowledge check
Knowledge check · 3 questions
Q1. Where does Ansible look for inventory by default?
Q2. Facts are gathered automatically on every playbook run.
Q3. Which of the following are valid Ansible facts? Select all that apply.
Passing score: 75%. Answers are checked in this browser.