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 Inventory: Static, Dynamic & Advanced Patterns (Complete Guide)

By Luca Berton · Published 2024-01-01 · Category: database-automation

Complete guide to Ansible inventory. Configure static INI and YAML inventories, dynamic inventory scripts, AWS/Azure/GCP plugins, host patterns, group.

The inventory defines what hosts Ansible manages and how to connect to them. It can be a simple INI file, YAML, a dynamic script pulling from cloud APIs, or a combination of all three.

Static Inventory (INI Format)

# inventory.ini

# Ungrouped hosts
mail.example.com

# Web servers
[webservers]
web1.example.com
web2.example.com
web3.example.com ansible_port=2222

# Database servers
[dbservers]
db1.example.com
db2.example.com

# Group of groups
[production:children]
webservers
dbservers

# Group variables
[webservers:vars]
http_port=80
ansible_user=deploy

[production:vars]
env=production
monitoring=true

Range Patterns

[webservers]
web[01:50].example.com     # web01 through web50

[dbservers]
db-[a:f].example.com       # db-a through db-f

See also: Learn Ansible: Complete Beginner's Guide & Learning Path (2026)

Static Inventory (YAML Format)

# inventory.yml
all:
  children:
    production:
      children:
        webservers:
          hosts:
            web1.example.com:
              http_port: 80
            web2.example.com:
              http_port: 8080
          vars:
            ansible_user: deploy
        
        dbservers:
          hosts:
            db1.example.com:
              db_port: 5432
            db2.example.com:
              db_port: 5432
          vars:
            ansible_user: dbadmin
      
      vars:
        env: production
        monitoring: true
    
    staging:
      children:
        staging_web:
          hosts:
            staging-web1.example.com:
        staging_db:
          hosts:
            staging-db1.example.com:
      vars:
        env: staging

Host and Group Variables

inventory/
├── hosts.yml              # Main inventory
├── group_vars/
│   ├── all.yml            # Variables for ALL hosts
│   ├── webservers.yml     # Variables for webservers group
│   ├── dbservers.yml      # Variables for dbservers group
│   └── production/
│       ├── vars.yml       # Production variables
│       └── vault.yml      # Encrypted production secrets
└── host_vars/
    ├── web1.example.com.yml
    └── db1.example.com.yml
# group_vars/all.yml
---
ntp_server: ntp.example.com
dns_servers:
  - 8.8.8.8
  - 8.8.4.4

# group_vars/webservers.yml
---
http_port: 80
max_connections: 1000
ssl_enabled: true

# host_vars/web1.example.com.yml
---
http_port: 8080  # Override for this host
ssl_cert: /etc/ssl/web1.pem

See also: Automate Text Capitalization with Ansible Playbooks

Dynamic Inventory

AWS EC2

# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
  - eu-west-1
filters:
  tag:Environment: production
  instance-state-name: running

keyed_groups:
  - key: tags.Role
    prefix: role
  - key: placement.region
    prefix: aws_region
  - key: instance_type
    prefix: type

hostnames:
  - tag:Name
  - private-ip-address

compose:
  ansible_host: private_ip_address
# Use dynamic inventory
ansible-playbook -i aws_ec2.yml site.yml

# Test / list hosts
ansible-inventory -i aws_ec2.yml --list
ansible-inventory -i aws_ec2.yml --graph

Azure

# azure_rm.yml
plugin: azure.azcollection.azure_rm
include_vm_resource_groups:
  - production-rg
auth_source: auto

keyed_groups:
  - key: tags.role | default('untagged')
    prefix: role
  - key: location
    prefix: azure_region

hostnames:
  - name
  - private_ipv4_addresses

GCP

# gcp_compute.yml
plugin: google.cloud.gcp_compute
projects:
  - my-gcp-project
zones:
  - us-central1-a
  - us-east1-b
filters:
  - status = RUNNING
auth_kind: serviceaccount
service_account_file: /path/to/sa.json

keyed_groups:
  - key: labels.env
    prefix: env

Custom Script

#!/usr/bin/env python3
# custom_inventory.py
import json
import sys

def get_inventory():
    return {
        "webservers": {
            "hosts": ["web1.example.com", "web2.example.com"],
            "vars": {"http_port": 80}
        },
        "dbservers": {
            "hosts": ["db1.example.com"],
            "vars": {"db_port": 5432}
        },
        "_meta": {
            "hostvars": {
                "web1.example.com": {"ansible_host": "10.0.0.1"},
                "web2.example.com": {"ansible_host": "10.0.0.2"},
                "db1.example.com": {"ansible_host": "10.0.0.10"}
            }
        }
    }

if __name__ == '__main__':
    if '--list' in sys.argv:
        print(json.dumps(get_inventory(), indent=2))
    elif '--host' in sys.argv:
        print(json.dumps({}))
chmod +x custom_inventory.py
ansible-playbook -i custom_inventory.py site.yml

Multiple Inventory Sources

# Combine static + dynamic
ansible-playbook -i inventory/static.yml -i inventory/aws_ec2.yml site.yml

# Use inventory directory
ansible-playbook -i inventory/ site.yml  # Reads all files in directory

See also: Ansible AWS EC2: Automate Ubuntu Instance Creation & Data Collection

Host Patterns

# All hosts
ansible all -m ping

# Specific group
ansible webservers -m ping

# Multiple groups (OR)
ansible 'webservers:dbservers' -m ping

# Intersection (AND)
ansible 'webservers:&production' -m ping

# Exclusion (NOT)
ansible 'production:!dbservers' -m ping

# Wildcards
ansible 'web*.example.com' -m ping

# Regex
ansible '~web[0-9]+\.example\.com' -m ping

# Specific host
ansible web1.example.com -m ping

# Index
ansible 'webservers[0]' -m ping      # First host
ansible 'webservers[-1]' -m ping     # Last host
ansible 'webservers[0:3]' -m ping    # First 3 hosts

Useful Commands

# List all hosts
ansible-inventory -i inventory.yml --list

# Show host graph
ansible-inventory -i inventory.yml --graph

# Show vars for a host
ansible-inventory -i inventory.yml --host web1.example.com

# Verify connectivity
ansible all -i inventory.yml -m ping

# Run ad-hoc command
ansible webservers -i inventory.yml -m command -a "uptime"

Best Practices

  1. Use YAML format — more readable than INI for complex inventories
  2. Use group_vars/ and host_vars/ — separate variables from host lists
  3. Encrypt secrets with Vaultgroup_vars/production/vault.yml
  4. Use dynamic inventory for cloud — keeps inventory in sync automatically
  5. Tag-based grouping — use keyed_groups with cloud tags
  6. One source of truth — don't duplicate hosts across files
  7. Test with ansible-inventory --graph — verify structure before running

FAQ

What is Ansible inventory?

The inventory is a file or script that lists the hosts Ansible manages, organized into groups. It defines connection parameters (IP, user, port) and variables. It can be a static file (INI/YAML) or dynamic (pulling from AWS, Azure, etc.).

What is the difference between static and dynamic inventory?

Static inventory is a manually maintained file (INI or YAML). Dynamic inventory is a script or plugin that queries an external source (cloud API, CMDB, LDAP) at runtime to generate the host list automatically.

Where is the default inventory file?

/etc/ansible/hosts is the default. Override with -i inventory.yml on the command line or inventory = ./inventory.yml in ansible.cfg.

How do I use group variables?

Create group_vars/.yml files next to your inventory. Variables defined there automatically apply to all hosts in that group. Use group_vars/all.yml for variables that apply everywhere.

How do I test if inventory is working?

Run ansible-inventory -i inventory.yml --graph to see the host structure, then ansible all -i inventory.yml -m ping to test connectivity.

Conclusion

  • INI or YAML — YAML preferred for complex inventories
  • group_vars/ + host_vars/ — organize variables cleanly
  • Dynamic inventory plugins — AWS, Azure, GCP, VMware
  • Host patternswebservers:&production:!dbservers for precise targeting
  • ansible-inventory --graph — always verify your inventory structure

Category: database-automation

Browse all Ansible tutorials · AnsiblePilot Home