Introduction
The inventory file tells Ansible which hosts to manage. It lists your servers, organizes them into groups, and assigns variables. You can write it in INI or YAML format, and it scales from a single server to thousands of hosts with dynamic inventory scripts.
INI Format
The most common format — simple and readable:
# /etc/ansible/hosts or ./inventory/hosts
# Ungrouped hosts
10.0.0.1
server1.example.com
# Web servers group
[webservers]
web-01 ansible_host=10.0.1.10
web-02 ansible_host=10.0.1.11
web-03 ansible_host=10.0.1.12
# Database servers group
[dbservers]
db-01 ansible_host=10.0.2.10
db-02 ansible_host=10.0.2.11
# Load balancers
[loadbalancers]
lb-01 ansible_host=10.0.0.5
YAML Format
More structured, supports complex data better:
# inventory/hosts.yml
all:
children:
webservers:
hosts:
web-01:
ansible_host: 10.0.1.10
web-02:
ansible_host: 10.0.1.11
web-03:
ansible_host: 10.0.1.12
dbservers:
hosts:
db-01:
ansible_host: 10.0.2.10
db-02:
ansible_host: 10.0.2.11
loadbalancers:
hosts:
lb-01:
ansible_host: 10.0.0.5
Host Variables
# INI — variables on the host line
[webservers]
web-01 ansible_host=10.0.1.10 ansible_user=deploy http_port=80
web-02 ansible_host=10.0.1.11 ansible_user=deploy http_port=8080
# Common connection variables
[dbservers]
db-01 ansible_host=10.0.2.10 ansible_port=2222 ansible_user=dbadmin
# YAML — cleaner for many variables
all:
children:
webservers:
hosts:
web-01:
ansible_host: 10.0.1.10
ansible_user: deploy
http_port: 80
web-02:
ansible_host: 10.0.1.11
ansible_user: deploy
http_port: 8080
Group Variables
# INI — group variables section
[webservers]
web-01
web-02
[webservers:vars]
ansible_user=deploy
http_port=80
document_root=/var/www/html
[dbservers]
db-01
db-02
[dbservers:vars]
ansible_user=dbadmin
db_port=5432
# YAML
all:
children:
webservers:
vars:
ansible_user: deploy
http_port: 80
document_root: /var/www/html
hosts:
web-01:
web-02:
Groups of Groups
# Parent group containing other groups
[webservers]
web-01
web-02
[dbservers]
db-01
[monitoring]
grafana-01
# Group of groups (children)
[production:children]
webservers
dbservers
[infrastructure:children]
loadbalancers
monitoring
# Variables for the parent group
[production:vars]
env=production
# YAML equivalent
all:
children:
production:
vars:
env: production
children:
webservers:
hosts:
web-01:
web-02:
dbservers:
hosts:
db-01:
infrastructure:
children:
loadbalancers:
hosts:
lb-01:
monitoring:
hosts:
grafana-01:
Host Ranges
# Numeric ranges
[webservers]
web-[01:20] # web-01, web-02, ... web-20
[dbservers]
db-[a:f].example.com # db-a.example.com through db-f.example.com
# With step
[webservers]
web-[01:20:2] # web-01, web-03, web-05, ... web-19 (odd only)
Common Connection Variables
| Variable | Description | Example |
|---|---|---|
ansible_host | IP or hostname to connect to | 10.0.1.10 |
ansible_port | SSH port | 2222 |
ansible_user | SSH username | deploy |
ansible_ssh_private_key_file | Path to SSH key | ~/.ssh/deploy_key |
ansible_python_interpreter | Python path on remote | /usr/bin/python3 |
ansible_connection | Connection type | ssh, local, winrm |
ansible_become | Enable privilege escalation | true |
ansible_become_user | User to become | root |
Inventory Directory Structure
For larger setups, use a directory with separate files:
inventory/
├── hosts # Main inventory file
├── group_vars/
│ ├── all.yml # Variables for ALL hosts
│ ├── webservers.yml # Variables for webservers group
│ ├── dbservers.yml
│ └── production/
│ ├── vars.yml # Plain vars
│ └── vault.yml # Encrypted secrets
└── host_vars/
├── web-01.yml # Variables for specific host
└── db-01.yml
# Use the directory as inventory
ansible-playbook -i inventory/ site.yml
Multiple Inventories
# Different inventories per environment
ansible-playbook -i inventory/production site.yml
ansible-playbook -i inventory/staging site.yml
# Or in ansible.cfg
# [defaults]
# inventory = ./inventory/production
Host Patterns
Target specific hosts or groups in commands:
# All hosts
ansible all -m ping
# Specific group
ansible webservers -m ping
# Specific host
ansible web-01 -m ping
# Multiple groups (union)
ansible 'webservers:dbservers' -m ping
# Intersection (hosts in BOTH groups)
ansible 'webservers:&production' -m ping
# Exclude (webservers NOT in staging)
ansible 'webservers:!staging' -m ping
# Wildcard
ansible 'web-*' -m ping
# Regex
ansible '~web-0[1-3]' -m ping
# First host in group
ansible 'webservers[0]' -m ping
Dynamic Inventory
For cloud environments, generate inventory dynamically:
# AWS EC2
ansible-playbook -i aws_ec2.yml site.yml
# GCP
ansible-playbook -i gcp_compute.yml site.yml
aws_ec2.yml:
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
- eu-west-1
keyed_groups:
- key: tags.Environment
prefix: env
- key: instance_type
prefix: type
filters:
tag:Managed: ansible
instance-state-name: running
Verify Your Inventory
# List all hosts
ansible-inventory -i inventory/ --list
# Show as graph
ansible-inventory -i inventory/ --graph
# Show specific host details
ansible-inventory -i inventory/ --host web-01
# Verify connectivity
ansible all -i inventory/ -m ping
Example graph output:
@all:
|--@production:
| |--@webservers:
| | |--web-01
| | |--web-02
| |--@dbservers:
| | |--db-01
|--@ungrouped:
| |--bastion
Localhost
# Run tasks on the control node itself
[local]
localhost ansible_connection=local
Or in a playbook:
- name: Run locally
hosts: localhost
connection: local
tasks:
- ansible.builtin.debug:
msg: "Running on control node"
Troubleshooting
"Could not match supplied host pattern"
The host or group doesn't exist in your inventory:
# Check what's in your inventory
ansible-inventory --list
# Verify the host exists
ansible-inventory --host web-01
Variables Not Loading from group_vars
Directory names must exactly match group names:
group_vars/webservers.yml # ✅ matches [webservers]
group_vars/Webservers.yml # ❌ case mismatch
group_vars/web-servers.yml # ❌ name mismatch
Related Articles
- Ansible inventory_hostname Explained
- Ansible Ping Module
- Ansible Variables Guide
- Ansible Galaxy Collections
- Ansible Facts Guide
Conclusion
The inventory file is the foundation of Ansible automation. Start with a simple INI file for small setups, move to YAML for complex variable structures, and use dynamic inventory for cloud environments. Organize variables in group_vars/ and host_vars/ directories to keep your inventory clean. Use ansible-inventory --graph to verify your host and group structure before running playbooks.