What is an Inventory?
Ansible needs to know what it is automating. By default, Ansible has no idea what servers you own.
An Inventory is simply a file containing a list of your servers (IP addresses or DNS names). It allows you to organize your servers into logical groups so you can target specific subsets of your infrastructure.
By default, Ansible looks for an inventory file at /etc/ansible/hosts, but it is best practice to keep your inventory file in the same directory as your project code.
Static Inventory Formats
Ansible supports two main formats for static inventories: INI and YAML.
1. The INI Format
This is the traditional, most commonly used format for simpler projects. It relies on brackets [ ] to define groups.
# A server not assigned to any specific group
192.168.1.10
# A group named "webservers"
[webservers]
web1.example.com
web2.example.com
10.0.0.50
# A group named "databases"
[databases]
db-primary.example.com
db-replica.example.com2. The YAML Format
The YAML format is more modern and makes it easier to pass complex variables to your servers directly within the inventory.
all:
hosts:
192.168.1.10:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
10.0.0.50:
databases:
hosts:
db-primary.example.com:
db-replica.example.com:Groups of Groups (Children)
Sometimes, you want to perform an action on all servers in a specific region, regardless of whether they are web servers or databases. You can establish group hierarchies using the :children suffix in INI format.
[web_eu]
eu-web-1.example.com
eu-web-2.example.com
[db_eu]
eu-db-1.example.com
# Create a master "europe" group that includes the groups above
[europe:children]
web_eu
db_euWhen you target the europe group, Ansible will execute against all three servers.
Inventory Variables
You can assign variables directly to hosts or groups in the inventory file. This is incredibly useful for setting SSH users, custom SSH ports, or application-specific flags.
Host Variables
Assigning a custom SSH port and user to a specific machine:
[webservers]
web1.example.com ansible_port=2222 ansible_user=admin
web2.example.com ansible_user=ubuntuGroup Variables
Assigning variables to an entire group using the :vars suffix:
[databases]
db-1.example.com
db-2.example.com
[databases:vars]
ansible_user=postgres
database_version=14.1Common Built-in Ansible Variables
| Variable | What it does |
|---|---|
ansible_user | The SSH username to connect with (default is your current local user). |
ansible_port | The SSH port to connect to (default is 22). |
ansible_ssh_private_key_file | The path to the private .pem or .id_rsa key for authentication. |
ansible_become | Boolean (true/false). Tells Ansible to use sudo. |
ansible_become_password | The sudo password (if required). Warning: Don't put plain text passwords in Git! Use Ansible Vault. |
ansible_python_interpreter | The path to Python on the target host (e.g., /usr/bin/python3). |
Verifying Your Inventory
Before running a massive automation script, you should verify that Ansible is reading your inventory file correctly.
If your inventory file is named inventory.ini, you can list all the hosts Ansible found using the --list-hosts flag:
# List all hosts in the inventory
ansible all -i inventory.ini --list-hosts
# List only the databases
ansible databases -i inventory.ini --list-hostsThe -i flag explicitly tells Ansible which inventory file to use. If you don't provide it, Ansible defaults to looking at /etc/ansible/hosts.
To avoid typing -i every time, you can configure an ansible.cfg file in your project directory.
Dynamic Inventories (Cloud Environments)
Static INI files are great if you manage your own physical servers. But what if you are using AWS, where servers scale up and down automatically every hour? You can't manually update an INI file every time an EC2 instance launches.
Dynamic Inventories solve this by replacing the static text file with a plugin or script that queries your cloud provider's API in real-time.
For example, using the aws_ec2 plugin, you can tell Ansible: "Target all EC2 instances currently running in us-east-1 that have the tag Role: Webserver."
# aws_ec2.yaml (Dynamic Inventory config)
plugin: aws_ec2
regions:
- us-east-1
keyed_groups:
- key: tags.Role
prefix: role_Ansible will dynamically create a group called role_Webserver on the fly based on AWS tags!