Files
howtos/topics/ansible-inventory.md
user 80f82dcde7 docs: add ansible howto collection
Four reference files covering:
- ansible.md — core commands, ansible.cfg, key settings
- ansible-inventory.md — static/dynamic inventory, directory layout
- ansible-variables.md — 22-level precedence, scoping, merge behavior
- ansible-roles.md — structure, defaults vs vars, dependencies
2026-02-21 20:33:34 +01:00

5.6 KiB

Ansible Inventory

Define which hosts to manage, how to group them, and where to find them.

Inventory Formats

INI Format

# inventory/hosts.ini

[webservers]
web1.example.com
web2.example.com ansible_port=2222

[dbservers]
db1.example.com ansible_user=postgres
db[1:3].example.com              # db1, db2, db3

[loadbalancers]
lb1.example.com

# Group of groups
[production:children]
webservers
dbservers
loadbalancers

# Group variables
[webservers:vars]
http_port=8080
app_env=production

[all:vars]
ansible_python_interpreter=/usr/bin/python3

YAML Format (preferred)

# inventory/hosts.yml
all:
  vars:
    ansible_python_interpreter: /usr/bin/python3
  children:
    production:
      children:
        webservers:
          hosts:
            web1.example.com:
            web2.example.com:
              ansible_port: 2222
          vars:
            http_port: 8080
        dbservers:
          hosts:
            db1.example.com:
              ansible_user: postgres
        loadbalancers:
          hosts:
            lb1.example.com:

Directory Layout

inventory/
├── hosts.yml              # Host definitions
├── group_vars/
│   ├── all.yml            # Vars for every host
│   ├── all/               # Dir form (merged, alphabetical)
│   │   ├── common.yml
│   │   └── vault.yml      # Encrypted secrets
│   ├── webservers.yml     # Vars for webservers group
│   └── production.yml     # Vars for production parent group
└── host_vars/
    ├── web1.example.com.yml
    └── db1.example.com/   # Dir form
        ├── main.yml
        └── vault.yml

Multiple Environments

inventories/
├── staging/
│   ├── hosts.yml
│   ├── group_vars/
│   └── host_vars/
└── production/
    ├── hosts.yml
    ├── group_vars/
    └── host_vars/
ansible-playbook site.yml -i inventories/staging/
ansible-playbook site.yml -i inventories/production/

Dynamic Inventories

Script-Based (legacy)

A script that outputs JSON when called with --list or --host <name>.

#!/usr/bin/env python3
# inventory/dynamic.py — must be executable (chmod +x)
import json, sys

def get_inventory():
    return {
        "webservers": {
            "hosts": ["web1.example.com", "web2.example.com"],
            "vars": {"http_port": 8080}
        },
        "dbservers": {
            "hosts": ["db1.example.com"]
        },
        "_meta": {
            "hostvars": {
                "web1.example.com": {"ansible_port": 22},
                "db1.example.com": {"ansible_user": "postgres"}
            }
        }
    }

if "--list" in sys.argv:
    print(json.dumps(get_inventory(), indent=2))
elif "--host" in sys.argv:
    host = sys.argv[sys.argv.index("--host") + 1]
    hostvars = get_inventory().get("_meta", {}).get("hostvars", {})
    print(json.dumps(hostvars.get(host, {})))

The _meta.hostvars key avoids per-host --host calls (efficiency).

Plugin-Based (modern, preferred)

# inventory/aws_ec2.yml — filename must end with the plugin suffix
plugin: amazon.aws.aws_ec2
regions:
  - eu-west-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type
filters:
  tag:Managed: ansible
compose:
  ansible_host: private_ip_address

Common inventory plugins:

Plugin Source Suffix
amazon.aws.aws_ec2 AWS EC2 aws_ec2.yml
azure.azcollection.azure_rm Azure azure_rm.yml
google.cloud.gcp_compute GCP gcp.yml
community.general.proxmox Proxmox proxmox.yml
community.docker.docker_containers Docker docker.yml
ansible.builtin.constructed Derived constructed.yml
# Verify dynamic inventory output
ansible-inventory -i inventory/aws_ec2.yml --graph
ansible-inventory -i inventory/aws_ec2.yml --list

Constructed Inventory (compose groups from existing data)

# inventory/constructed.yml
plugin: ansible.builtin.constructed
strict: false
groups:
  is_debian: ansible_os_family == "Debian"
  is_large: ansible_memtotal_mb > 8192
keyed_groups:
  - key: ansible_distribution | lower
    prefix: os

Special Variables

Variable Purpose
ansible_host IP/hostname to connect to
ansible_port SSH port (default: 22)
ansible_user SSH user
ansible_ssh_private_key_file SSH key path
ansible_become Enable privilege escalation
ansible_connection Connection type (ssh, local)
ansible_python_interpreter Python path on target

Gotchas

  • Script inventories must be executable (chmod +x) and have a shebang
  • Plugin inventory files must end with the correct suffix or be listed in enable_plugins
  • group_vars/ directory must sit next to the inventory file, or at playbook level
  • YAML inventory: hosts need trailing colon even with no vars (web1.example.com:)
  • Groups named all and ungrouped are implicit — don't redefine them
  • Directory form group_vars/all/ merges files alphabetically — name carefully

See Also

  • ansible — core commands and ansible.cfg
  • ansible-variables — variable precedence across inventory layers
  • ansible-roles — role structure and organization