Table of Contents
- Overview
- Inventory File Locations & Structure
- Example: INI Format
- Example: YAML Format
- Logical Grouping Guidelines
- Example: Hierarchical Group Structure
- Assigning Variables
- YAML Example
- INI Example
- Inventory Verification
- Best Practices
- Pre-defined Variables
- Conclusion
Ansible Inventory: Overview
What Is Ansible Inventory?
Ansible inventory is the foundational component that tells Ansible which devices, servers, or nodes it will manage. It’s essentially a list or organizational map of your infrastructure—ranging from a handful of servers to thousands of devices—informing Ansible where to run automation tasks.
Why Do You Need to Know About It?
- Central to Automation: The inventory is required for every Ansible operation. Without knowing what’s in your environment (and how to group and target those assets), automation quickly becomes unreliable or error-prone.
- Dynamic Targeting: Inventories make it possible to run tasks against all hosts, specific groups (like
webservers
ordbservers
), or just a single system—empowering you to automate with precision. - Scalability: As environments grow or change, Ansible inventory supports both static and dynamic sources, letting you scale from simple text lists to automatically-updating inventories (like those sourced from cloud APIs).
- Repeatability & Consistency: Well-structured inventories help ensure that every automation run is predictable, auditable, and consistent across environments such as dev, staging, or production.
How Does It Work?
- Inventory Formats: Inventories can be written in simple INI files, structured YAML files, or generated dynamically by scripts or plugins (for integration with cloud platforms or CMDBs).
- Grouping: Hosts are logically grouped by function (web, database), site, or environment. Groups can be nested—so you can, for example, target “all database servers in production.”
- Variable Assignment: Inventories aren’t just lists—they’re also where you start assigning host-specific or group-wide variables (such as management IPs, operating system type, or login credentials).
- Execution Flow:
- Define your inventory and groups (in files or directories).
- Assign variables as needed at host or group level.
- Use inventory targets (groups, hosts) in playbooks or ad-hoc commands.
- Ansible resolves all hosts and variables at runtime, then orchestrates tasks accordingly.
Key Takeaways
- The Ansible inventory is the blueprint for automation: without it, Ansible won’t know what to automate.
- Clear, flexible inventories allow you to target the right hosts, control large infrastructures, and keep automation under control as your network grows.
- Understanding and organizing the inventory well leads to smoother automation, less risk, and more maintainable operations—whether you’re managing 10 devices or 10,000.
Inventory File Locations & Structure
Ansible inventories define which systems your automation will manage. Understanding where the inventory file is located and how it's structured is essential for efficient provisioning and configuration. Let's walk through this step by step:
-
Locate the Default Inventory File:
By default, Ansible uses the file at/etc/ansible/hosts
as the primary inventory. This file can be in either INI or YAML format. -
Use a Custom Inventory File:
You can specify a custom inventory using the-i
flag when running a playbook:
ansible-playbook -i inventories/lab_site site.yml
This allows flexibility to use different inventories per environment (e.g., dev, staging, prod). -
Structure Your Inventory with INI Format:
An example of an INI-formatted inventory file:[web] web01.example.com web02.example.com [db] db01.example.com ansible_user=admin ansible_port=2222 [monitoring:children] web db
Groups like[web]
and[db]
help organize hosts by role or function. You can create parent-child relationships like[monitoring:children]
to combine groups. -
Use YAML for Hierarchical Inventories:
Starting from Ansible 2.4+, inventory files can also be written in YAML format:all: children: web: hosts: web01.example.com: web02.example.com: db: hosts: db01.example.com: ansible_user: admin ansible_port: 2222
YAML format adds readability, especially for larger environments with complex variables and hierarchies. -
Inventory Directory Support:
Instead of a single file, you can organize your inventory as a directory. This allows you to split inventories by site, region, or function. Example:inventory/ ├── lab_site/ │ ├── hosts.yml │ └── group_vars/ │ └── all.yml
When using this structure, just point to the directory in the-i
flag:ansible-playbook -i inventory/lab_site site.yml
-
Verify the Inventory Structure:
Use Ansible’s built-in inventory validation tool:ansible-inventory -i inventory/lab_site --list
This helps confirm your structure and variables are loaded correctly.
Organizing your inventory well reduces complexity and keeps your automation consistent across environments. Use directories for scale and YAML for clarity where possible.
Example: INI Format
The INI format is the traditional and widely used inventory style in Ansible. It organizes hosts into groups using square bracket notation and allows inline variable definitions. Here's how it works, step by step:
-
Start with Host Declarations:
You can begin by simply listing individual hosts line-by-line:host1.example.com host2.example.com
This is valid but not scalable. Grouping is recommended for clarity and reusability. -
Create Groups Using Brackets:
Use brackets to define logical groups of hosts:[webservers] web01.example.com web02.example.com [dbservers] db01.example.com db02.example.com
These group names can be referenced in playbooks to target a defined set of systems. -
Assign Host-Level Variables Inline:
You can define variables for a specific host directly on the same line:db01.example.com ansible_user=dbadmin ansible_port=2222
This is useful for defining SSH users, ports, and other connection parameters without needing separate variable files. -
Create Nested Groups with
:children
Suffix:
Use this to define parent groups that include other groups:[app:children] webservers dbservers
This allows you to organize your infrastructure hierarchically, targeting broader functional groups. -
Combine Groups and Hosts with Clear Labels:
A complete INI inventory example:[web] web01 ansible_host=192.168.1.10 ansible_user=webadmin web02 ansible_host=192.168.1.11 ansible_user=webadmin [db] db01 ansible_host=192.168.1.20 ansible_user=dbadmin ansible_port=2222 [backend:children] web db
Here, we logically grouped both `web` and `db` under the `backend` umbrella, allowing us to run playbooks against all backend servers.
The INI format is ideal for quick inventory management and is well-suited for simple to moderately complex environments that don’t require deep nesting or complex metadata.
Example: YAML Format
YAML format provides a more expressive and structured way to define your Ansible inventory. It is ideal for larger or more complex environments where hierarchy, nesting, or detailed host variables are needed. Here's a step-by-step guide:
-
Start with the
all
Group:
All inventories start with a top-levelall
group. This group contains all managed hosts either directly or through child groups.all: children: web: db:
Thechildren
key allows you to nest groups under theall
umbrella. -
Define Host Groups with Hosts Inside:
Within each group, use thehosts
key to list each host.web: hosts: web01.example.com: web02.example.com: db: hosts: db01.example.com: db02.example.com:
In YAML format, hosts are listed as dictionary keys, which allows for attaching host-specific variables directly. -
Assign Variables to Individual Hosts:
Each host can contain variable definitions beneath its key:db01.example.com: ansible_user: dbadmin ansible_port: 2222
This improves readability and keeps your configuration clean and well-structured. -
Use Group Variables:
You can define variables shared by multiple hosts at the group level using thevars
key:web: hosts: web01.example.com: web02.example.com: vars: ansible_user: webadmin nginx_port: 8080
Group variables reduce duplication and help ensure consistency across common roles. -
Full YAML Inventory Example:
Here’s what a complete, well-structured YAML inventory might look like:all: children: web: hosts: web01.example.com: web02.example.com: vars: ansible_user: webadmin db: hosts: db01.example.com: ansible_user: dbadmin ansible_port: 2222 db02.example.com: ansible_user: dbadmin ansible_port: 2222 backend: children: web: db:
Thebackend
group includes bothweb
anddb
groups. This setup is powerful when using roles or targeting subsets of hosts in different deployment stages.
YAML format is particularly useful when you need readability, deeper nesting, or host-level variables. It's highly recommended for complex inventories or when using version control and automation pipelines.
Logical Grouping Guidelines
Grouping hosts logically is essential for effective automation and targeted actions in your Ansible inventory. Below is a step-by-step guide to creating logical, maintainable group structure:
-
Identify Grouping Criteria:
Start by considering what, where, and when:- What: Group by function (e.g.,
web
,db
,app
,network
). - Where: Group by location (e.g.,
datacenter
,region
,floor_19
). - When: Group by environment or life-cycle (e.g.,
dev
,staging
,prod
).
- What: Group by function (e.g.,
-
Define Groups Using Appropriate Naming:
- Use clear, human-readable names that reflect purpose or location.
- Avoid spaces, hyphens, and leading numbers.
- Prefer snake_case for group names (e.g.,
web_servers
,prod_db
). - Group names are case-sensitive and must be unique.
Example of good group names:
[web_servers] [db_servers] [prod_network] [floor_19]
-
Utilize Parent (Metagroups) and Child Groups:
Nest groups to build hierarchy and reduce repetition. Use parent groups to logically contain other groups:[network_devices:children] core_routers access_switches firewalls [core_routers] router1 router2
This structure lets you target broad categories or specific devices in your automation. -
Assign Hosts to Multiple Groups for Flexible Targeting:
Hosts can belong to more than one group. This provides versatility, such as targeting by both function and environment.[web] web01.example.com web02.example.com [production] web01.example.com db01.example.com
Here,web01.example.com
is part of bothweb
andproduction
. -
Consider Group Variables and Inheritance:
Assign variables at the group level for shared configuration.[web:vars] ansible_user=webadmin nginx_port=8080
Child groups and their hosts inherit variables from parent groups, but explicit definitions can override inherited values. -
Keep Your Group Hierarchy Logical and Maintainable:
Regularly review and refine your groups. Break up monolithic groups into logical tiers as your environment grows. Use environment, function, and location together for precise, scalable targeting.[all:children] network_devices web_servers db_servers dev staging prod
Establishing a clear grouping structure reduces complexity, enhances scalability, and simplifies the management of your infrastructure automation. Well-named, logical groups make Playbooks and day-to-day operations intuitive and error-resistant.
Example: Hierarchical Group Structure
As your infrastructure grows, organizing your inventory in a hierarchical structure becomes essential. This allows for efficient targeting, configuration inheritance, and logical clarity. Here's how to build a hierarchical group structure step by step:
-
Start with Leaf-Level Device Groups:
Define your devices or hosts into functional groups at the base layer:[leafs] leaf01 leaf02 [spines] spine01 spine02
These groups represent specific device roles or hardware layers in your network or infrastructure. -
Create Higher-Level Groups Using
:children
:
Use the:children
keyword to build parent groups that include multiple functional units:[network:children] leafs spines
This allows Ansible to target all devices in thenetwork
group when needed. -
Continue Nesting to Reflect Real-World Topology:
You can add another parent group that includes the entire datacenter infrastructure:[webservers] web01 web02 [datacenter:children] network webservers
Now, running a playbook against thedatacenter
group will apply to both networking and compute resources. -
Use Clear Descriptive Group Names:
Choose names that describe the role, function, or location of the underlying assets:leafs
= Top-of-rack switchesspines
= Core aggregation switcheswebservers
= Frontend application serversnetwork
= Logical grouping of network devicesdatacenter
= Entire infrastructure within a location
-
Full INI Example for Reference:
[leafs] leaf01 leaf02 [spines] spine01 spine02 [network:children] leafs spines [webservers] web01 web02 [datacenter:children] network webservers
-
Equivalent YAML Structure:
YAML format can represent the same hierarchy clearly:all: children: leafs: hosts: leaf01: leaf02: spines: hosts: spine01: spine02: network: children: leafs: spines: webservers: hosts: web01: web02: datacenter: children: network: webservers:
This format is ideal for complex infrastructure where readability and nesting are priorities.
Using hierarchical group structures keeps your inventory scalable, maintainable, and aligned with the real-world topology of your systems. It enables bulk automation at every meaningful layer of your environment.
Assigning Variables
Variables allow you to customize how Ansible interacts with managed hosts. They can be defined at the host, group, or global level to specify connection details, credentials, platform-specific options, and more. Here's how to assign variables step by step:
-
Assign Variables Inline in INI Format:
You can define variables directly on a host’s line in an INI inventory:web01 ansible_host=192.168.10.10 ansible_user=admin ansible_port=2222
This works well for small inventories with minimal variables. However, for scalability and manageability, other methods are preferred. -
Define Host-Level Variables in YAML:
YAML offers a clean way to assign variables per host:web01.example.com: ansible_host: 192.168.10.10 ansible_user: admin ansible_port: 2222 ansible_connection: ssh
This is particularly useful when using complex inventory files with nested structure. -
Use Group-Level Variables with
[group:vars]
in INI:
You can apply variables to all group members using the:vars
suffix:[web:vars] ansible_user=webadmin nginx_port=8080
These variables apply to every host in the[web]
group unless overridden by host-specific variables. -
Use
vars
in YAML Group Structure:
When using YAML inventory format, attach group-wide variables using thevars
keyword:web: hosts: web01.example.com: web02.example.com: vars: ansible_user: webadmin nginx_port: 8080 ansible_connection: ssh
This keeps common configurations DRY (Don't Repeat Yourself). -
Create
group_vars
andhost_vars
Directories:
Ansible automatically loads variables from files placed in these folders:inventory/ ├── production/ │ ├── hosts.yml │ ├── group_vars/ │ │ ├── web.yml │ │ └── db.yml │ └── host_vars/ │ ├── web01.yml │ └── db01.yml
This structure helps manage larger inventories and separate secrets or sensitive configurations from inventory logic. -
Override Precedence:
Variables follow a precedence hierarchy. Here’s the simplified order (from lowest to highest):- Inventory group variables
- Inventory host variables
- Playbook-level variables
- Extra vars (passed in with
-e
)
Strategically assigning variables allows you to scale configurations, reuse assets, and apply consistent logic across your playbooks and environments. Stick to predictable naming conventions and use group- or host-based directories for maintainability.
YAML Example
The YAML inventory format unlocks rich structure and greater readability for even the most complex environments. Here’s a step-by-step walk-through to build an effective YAML inventory for Ansible:
-
Begin with the Top-Level
all
Group:
All YAML inventories must start with theall
group, which contains the entirety of your environment.all: children: webservers: dbservers: monitoring:
Thechildren
key allows you to branch out into multiple sub-groups as your setup expands. -
Define Hosts within Each Group:
Organize related machines under groups with thehosts
key, which maps each hostname.webservers: hosts: web01.example.com: web02.example.com: dbservers: hosts: db01.example.com: db02.example.com: monitoring: hosts: monitor01.example.com:
This allows direct targeting of all hosts in a group, supporting scalability and clarity. -
Add Host Variables as Needed:
Attach host-specific variables directly under each hostname for tailored configuration.db01.example.com: ansible_user: dbadmin ansible_port: 2222
This method keeps sensitive or unique connection details easy to find and update. -
Use Group Variables for Shared Settings:
Specify settings that apply to an entire group using thevars
key.webservers: hosts: web01.example.com: web02.example.com: vars: ansible_user: webadmin nginx_port: 8080
Keeping common variables at the group level avoids duplication across hosts. -
Demonstrate a Complete YAML Inventory Example:
all: children: webservers: hosts: web01.example.com: web02.example.com: vars: ansible_user: webadmin nginx_port: 8080 dbservers: hosts: db01.example.com: ansible_user: dbadmin ansible_port: 2222 db02.example.com: ansible_user: dbadmin ansible_port: 2222 monitoring: hosts: monitor01.example.com: staging: children: webservers: dbservers:
This organizes machines by function and allows you to inherit or override variables as needed, streamlining both small and complex inventories.
With YAML, your inventory remains orderly and scalable as your infrastructure grows, making changes easier and safer over time.
INI Example
The INI format is the classic and foundational way to define your Ansible inventory. It’s simple, easy to read, and ideal for smaller environments or quick setups. Below is a step-by-step walkthrough to build a structured INI inventory.
-
Start by Defining Host Groups:
Group your hosts based on functionality or purpose using square brackets.[webservers] web01.example.com web02.example.com [dbservers] db01.example.com db02.example.com
These group names can be referenced in your playbooks to apply tasks to specific sets of hosts. -
Add Host-Level Variables Inline:
You can define connection-specific variables next to each host.db01.example.com ansible_user=dbadmin ansible_port=2222
This keeps per-host values visible directly in the inventory file. -
Use a Group with Variables:
Define variables used by all hosts in a group using the:vars
suffix.[webservers:vars] ansible_user=webadmin nginx_port=8080
This helps reduce repetition by setting shared values once for all members. -
Create Nested Groups with
:children
:
Build a hierarchical structure by nesting groups.[backend:children] webservers dbservers
Now, you can target[backend]
in your playbooks and automatically include both web and database hosts. -
Complete INI Inventory Example:
Here's a full example combining groupings, nesting, and variables:[webservers] web01.example.com web02.example.com [webservers:vars] ansible_user=webadmin ansible_port=22 [dbservers] db01.example.com ansible_user=dbadmin ansible_port=2222 db02.example.com ansible_user=dbadmin ansible_port=2222 [backend:children] webservers dbservers [monitoring] monitor01.example.com ansible_user=monitoradmin [environment:children] backend monitoring
This structure allows you to run Ansible tasks at multiple levels: individual hosts, role-based groups, or full environments.
The INI format, while less scalable than YAML for complex inventories, is still powerful and extremely effective when used with clear groupings and straightforward hierarchies.
Inventory Verification
Before deploying playbooks or automation tasks, it’s vital to verify your Ansible inventory. This ensures that your hosts, groups, and variables are correctly structured and accessible. Here’s a step-by-step guide to verifying your inventory:
-
Preview the Inventory Structure:
Use theansible-inventory
command to display your inventory as Ansible understands it. This outputs a complete breakdown of hosts, groups, and variables.ansible-inventory -i inventory.yml --list
The output will be in JSON or YAML format, depending on your options, allowing you to review all details at a glance. -
Visualize Group Hierarchy:
To see how groups and hosts are organized, use the--graph
option:ansible-inventory -i inventory.yml --graph
This provides a visual hierarchy, making it easy to confirm relationships between groups and hosts. -
Test Host Connectivity:
Verify that each host is reachable by using theping
module:ansible -i inventory.yml all -m ping
A successful response indicates Ansible can connect to your hosts. If a host isn't reachable, you'll see an error message, identifying issues before any real task runs. -
Inspect Host Variables:
To confirm variables are set and inherited as expected, use thedebug
module:ansible -i inventory.yml all -m debug -a "var=hostvars[inventory_hostname]"
This displays all variables resolved for each host, ensuring your configuration is accurate. -
List Hosts Matching Specific Criteria:
To verify group membership or host targeting, leverage the--list-hosts
option:ansible -i inventory.yml web --list-hosts
This will display a list of hosts in the specified group, helping validate group assignments.
Consistently verifying your inventory helps catch errors early, improves reliability, and keeps your automation secure and predictable. Make it part of your workflow whenever you change your inventory or make environment upgrades.
Best Practices
Following best practices when managing your Ansible inventory ensures scalability, readability, and long-term maintainability. Below is a step-by-step guide highlighting practical strategies for building clean and effective inventories:
-
Use Descriptive Group Names:
Name groups based on purpose, environment, or location. Avoid ambiguous names likegroup1
ormisc
.- âś…
web_servers
,db_prod
,network_devices
- ❌
testgroup
,xyz
,123group
- âś…
-
Avoid Hardcoding IPs Inline (When Possible):
Useansible_host
to define IPs instead of replacing the hostname. This keeps inventories readable and flexible:web01 ansible_host=10.0.0.11 ansible_user=admin
-
Separate Variables from Hosts:
Move variables out of the inventory file and intogroup_vars/
andhost_vars/
directories:inventory/ ├── production/ │ ├── hosts.yml │ ├── group_vars/ │ │ └── web_servers.yml │ └── host_vars/ │ └── web01.yml
This provides version control benefits and avoids clutter in your inventory file. -
Organize Inventory by Environment:
Use separate folders or files fordev
,staging
, andproduction
inventories:inventory/ ├── dev/ ├── staging/ └── production/
This enables safe modification and consistent policies per environment. -
Prefer YAML Format for Larger Environments:
YAML inventories are more readable and handle nested structures better than INI. Use YAML when working with complex infrastructure. -
Use Group Nesting Thoughtfully:
Don’t over-engineer group hierarchies. Keep them intuitive and only as deep as needed to reflect logical or operational boundaries. -
Keep Sensitive Info External:
Never store passwords, secrets, or keys directly inside your inventory. Instead, use Ansible Vault or fetch them dynamically through lookups. -
Verify Frequently:
Run checks after every change using:ansible-inventory -i inventory/production --list ansible -i inventory/production all -m ping
This ensures your inventory is up-to-date and functional.
Applying these best practices will save time, reduce errors, and make your infrastructure easier to manage at scale. Clean inventory leads to clean automation — plan it like code.
Pre-defined Variables
Ansible provides a wide range of pre-defined variables that it automatically detects or makes available during inventory parsing and playbook execution. These are useful for customizing behavior, making decisions in tasks, and controlling how Ansible connects to hosts. Here's a step-by-step guide to key pre-defined variables you can use effectively:
-
inventory_hostname
:
Represents the name of the host as configured in the inventory file (not necessarily the DNS name).- debug: msg: "This task is running on {{ inventory_hostname }}"
-
ansible_hostname
:
The short hostname of the system as gathered by the setup module (facts). It reflects the name reported by the OS.- debug: msg: "Host OS name is {{ ansible_hostname }}"
-
ansible_host
:
The address or IP that Ansible should use to connect to the host. This can differ frominventory_hostname
.[web] web01 ansible_host=10.1.1.25
This allows you to connect via IP or alternate DNS name while keeping a consistent logic name. -
group_names
:
A list of groups that the current host belongs to. Useful for conditional tasks based on group membership.- debug: var: group_names
-
groups
dictionary:
A full dictionary structure containing every group and its member hosts.- debug: msg: "Web servers: {{ groups['web'] }}"
This lets you dynamically reference and automate actions across multiple groups. -
hostvars
:
A dictionary of all variables (defined or gathered) for each host in the inventory.- debug: var: hostvars['web01']['ansible_host']
You can reference one host’s variables from another, helpful for coordination logic across systems. -
ansible_connection
:
Controls how Ansible connects to the host. Common values include:ssh
: Default for Linux systemswinrm
: For Windows hostslocal
: Used for local execution or delegationhttpapi
,netconf
,network_cli
: For network devices
ansible_connection: network_cli
-
ansible_user
andansible_password
:
Use these to specify connection credentials if they differ per host or group.[db] db01 ansible_user=dbadmin ansible_password=StrongPassword123
You should secure sensitive values using Ansible Vault or environment variables rather than exposing them in plain text.
Understanding and leveraging pre-defined variables allows you to write smarter, more adaptable playbooks. These variables give you visibility into your execution environment and enable dynamic decision-making across your infrastructure.
Conclusion
Throughout this blog post, we explored the full anatomy of an Ansible inventory — one of the most vital building blocks in infrastructure automation.
Here’s a quick wrap-up of what we’ve learned:
- Inventory File Formats: You can use both INI (simple and fast) and YAML (powerful and structured) formats to define your inventory.
- Group Organization: Logical groupings help you abstract your systems by function, location, and environment — enabling scalable and targeted automation.
- Hierarchical Structuring: Child and parent groups let you layer your inventory, making it easier to manage even the most complex configurations.
- Variable Assignment: Variables can be attached at the host, group, or file level — giving you flexibility and control over how each host is configured or accessed.
- Validation & Debugging: Tools like
ansible-inventory
andansible -m ping
help verify that your inventory is well-structured and operational. - Best Practices: Using
group_vars
/host_vars
, avoiding hardcoded secrets, separating environments, and validating changes all lead to cleaner, more secure automation. - Pre-defined Variables: Ansible’s built-in variables allow you to dynamically extract inventory metadata and tailor behavior across environments.
By mastering your inventory, you lay the foundation for every playbook, role, and task Ansible executes. Whether you're managing 5 nodes or 5,000, a clean and logical inventory makes everything from debugging to scaling simpler.
Thanks for hanging out with us as we broke down the Ansible inventory system step by step. Hope this guide brought clarity, sparked some ideas, or shaved hours off your automation efforts.
Happy automating — and may your playbooks always run green!