| |

LFCE 148 ๐Ÿง Ansible โ€” Inventory and Config

โฑ๏ธ Estimated read: 11 min | |

The inventory and the configuration file are the two inputs that determine what Ansible does and how it does it. The inventory defines the hosts and groups that a playbook can target, along with the variables that describe each host’s connection details and role. The configuration file defines the behavior of the control node itself: where to find the inventory, how many hosts to manage in parallel, whether to gather facts, and how to format the output. Both are plain text, both are version-controllable, and both have a defined precedence order that determines which value wins when the same setting is defined in more than one place.

This chapter covers the inventory formats (INI and YAML), the host and group variables that control connection behavior, the group_vars and host_vars directories that organize variables outside the inventory file, and the ansible.cfg file with its search order and its most important settings.

Key point: The inventory defines the targets and their variables. The ansible.cfg defines the control node’s behavior. When the same variable is defined in multiple places, the last definition wins, and the group_vars and host_vars directories take precedence over the inline inventory variables.


Why inventory and config are separate

The target problem. A playbook is written once and run against different environments. The inventory is the file that changes between environments: the staging inventory lists staging hosts, the production inventory lists production hosts. The playbook references group names, not host names, and the inventory resolves those groups to the actual machines .

The behavior problem. The control node’s behavior is not the same for every project. One project needs 20 parallel forks and fact caching; another needs a single fork for a serial deployment. The ansible.cfg file is the per-project configuration that controls this behavior without changing the playbook or the inventory .

The precedence problem. Ansible has a defined precedence order for both variables and configuration settings. For configuration, the ANSIBLE_CONFIG environment variable wins over the project ansible.cfg, which wins over the home directory ansible.cfg, which wins over /etc/ansible/ansible.cfg . For variables, the more specific definition wins: host variables override group variables, and host_vars files override inline inventory variables .


a. The inventory formats and connection variables

An inventory can be an INI file or a YAML file. The INI format uses group headers in brackets and host lines with key=value connection variables.

[webservers]
web1.example.com ansible_host=10.0.1.10 ansible_port=22 ansible_user=deploy
web2.example.com ansible_host=10.0.1.11 ansible_port=2222 ansible_user=webadmin

[databases]
db1.example.com ansible_host=10.0.2.10 ansible_user=dbadmin

The connection variables control how Ansible reaches each host. ansible_host is the resolvable name or IP, which is useful when the inventory alias is not the actual address. ansible_port changes the SSH port. ansible_user sets the SSH username. ansible_ssh_private_key_file specifies a key file for a host that does not use the default key .

The YAML format is the recommended choice for new inventories because it handles variable types consistently. The INI format parses :vars sections as strings, which means a boolean false becomes the string "FALSE" unless a filter is applied in the playbook .

all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 10.0.1.10
        web2.example.com:
          ansible_host: 10.0.1.11

The group names in the inventory are the names referenced in the playbook’s hosts line. A group can have child groups, and the parent-child relationship determines the variable merge order .


b. The group_vars and host_vars directories

The inline inventory variables are convenient for a few settings, but they do not scale. The group_vars and host_vars directories are the standard way to organize variables. The group_vars/all file applies to every host, group_vars/webservers applies to the webservers group, and host_vars/web1.example.com applies to that specific host .

inventory/
  hosts.ini
  group_vars/
    all.yml
    webservers.yml
  host_vars/
    web1.example.com.yml

The variables in these files are YAML, and they can contain lists and dictionaries, which the INI inline format cannot. The load order is: group variables from the inventory file, then group_vars/all, then child group variables, then host variables from the inventory, then host_vars. The later definition wins .

The ansible_group_priority variable controls the merge order for groups of the same level. A higher number means the group is merged later, giving it higher priority. This variable can only be set in the inventory source, not in group_vars .


c. The ansible.cfg file

The configuration file uses INI syntax with sections. The [defaults] section contains the most important settings.

[defaults]
inventory = inventory/
remote_user = deploy
forks = 20
host_key_checking = False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600

[privilege_escalation]
become = True
become_method = sudo
become_user = root

The inventory setting points to the inventory file or directory. The forks setting controls how many hosts are managed in parallel; the default is 5, and a larger fleet benefits from a higher value . The gathering and fact_caching settings control whether facts are collected and whether they are cached between runs. The host_key_checking setting disables the SSH host key prompt, which is appropriate for a lab but not for production.

The [privilege_escalation] section sets the default become behavior, which removes the need to add become: true to every play .

The configuration search order is ANSIBLE_CONFIG, then ./ansible.cfg, then ~/.ansible.cfg, then /etc/ansible/ansible.cfg. The first file found is used, and the others are ignored .


Complete Example Session

# ============================================
# PART 1: THE INI INVENTORY
# ============================================
[webservers]
web1.example.com ansible_host=10.0.1.10 ansible_user=deploy
web2.example.com ansible_host=10.0.1.11 ansible_port=2222

[databases]
db1.example.com ansible_host=10.0.2.10 ansible_user=dbadmin
# ============================================
# PART 2: THE YAML INVENTORY
# ============================================
all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 10.0.1.10
    databases:
      hosts:
        db1.example.com:
          ansible_host: 10.0.2.10
# ============================================
# PART 3: THE GROUP_VARS FILE
# ============================================
# group_vars/all.yml
ansible_user: deploy
ansible_ssh_private_key_file: ~/.ssh/ansible_key
# ============================================
# PART 4: THE HOST_VARS FILE
# ============================================
# host_vars/web1.example.com.yml
ansible_host: 10.0.1.10
ansible_port: 2222
# ============================================
# PART 5: THE ANSIBLE.CFG
# ============================================
[defaults]
inventory = inventory/
forks = 20
host_key_checking = False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts

[privilege_escalation]
become = True
become_user = root
# ============================================
# PART 6: VERIFY THE INVENTORY
# ============================================
ansible-inventory --list -i inventory/
ansible all -m ping
# ============================================
# PART 7: THE PRECEDENCE CHECK
# ============================================
# host_vars/web1.example.com.yml defines ansible_port: 2222
# group_vars/all.yml defines ansible_port: 22
# Result: 2222, because host_vars wins.
# ============================================
# PART 8: THE CONFIG SEARCH ORDER
# ============================================
# 1. ANSIBLE_CONFIG
# 2. ./ansible.cfg
# 3. ~/.ansible.cfg
# 4. /etc/ansible/ansible.cfg
# The first one found is used.
# ============================================
# PART 9: THE DYNAMIC INVENTORY
# ============================================
# A plugin source instead of a static file.
# The plugin queries the cloud API.
# ansible-inventory --list shows the result.
# ============================================
# PART 10: THE COMPLETE PROJECT
# ============================================
# project/
#   ansible.cfg
#   inventory/
#     hosts.ini
#     group_vars/all.yml
#     host_vars/web1.example.com.yml
#   site.yml

The ten parts covered the INI inventory, the YAML inventory, the group_vars file, the host_vars file, the ansible.cfg, the inventory verification, the precedence check, the config search order, the dynamic inventory, and the complete project.


Quick Reference

Inventory formats

FormatVariable typingRecommended
INIStrings in :vars, literals inlineLegacy
YAMLConsistent typingNew projects
Dynamic pluginFrom cloud APIDynamic environments

Connection variables

VariablePurpose
ansible_hostIP or hostname to connect to
ansible_portSSH port
ansible_userSSH username
ansible_ssh_private_key_fileSSH key path
ansible_python_interpreterPython path on the target
ansible_connectionConnection plugin (ssh, winrm)

Variable precedence (lowest to highest)

OrderSource
1Group vars in inventory
2group_vars/all
3Child group vars
4Host vars in inventory
5host_vars/

ansible.cfg search order

OrderLocation
1ANSIBLE_CONFIG env var
2./ansible.cfg
3~/.ansible.cfg
4/etc/ansible/ansible.cfg

Key ansible.cfg settings

SettingPurpose
inventoryPath to inventory file or directory
forksParallel hosts (default 5)
remote_userDefault SSH user
host_key_checkingSSH host key verification
gatheringFact gathering mode
fact_cachingFact cache plugin

Best Practices

โœ… Do This:

# Use YAML inventory for consistent typing
all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 10.0.1.10                          # โœ…
# Use group_vars and host_vars for variables
# group_vars/all.yml
ansible_user: deploy                                       # โœ…
# Set forks for larger fleets
forks = 20                                                 # โœ…
# Enable fact caching
gathering = smart
fact_caching = jsonfile                                    # โœ…

โŒ Don’t Do This:

# Rely on INI :vars for typed values
[all:vars]
my_bool=FALSE  # parsed as the string "FALSE"              # โŒ
# Disable host key checking in production
host_key_checking = False                                  # โŒ
# Put all variables in the inventory file
# Use group_vars and host_vars instead                     # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Hosts not foundInventory path wrong in ansible.cfgCheck inventory = inventory/
Connection failsansible_user or key not setSet in group_vars or host_vars
Variable type is wrongINI :vars parses as stringUse YAML inventory or a filter
Config not appliedA different ansible.cfg is found firstCheck the search order; use ANSIBLE_CONFIG
Group variable overriddenHost variable definedCheck precedence; host wins
Parallelism too lowDefault forks = 5Increase forks in ansible.cfg

Real-World Examples

1. INI inventory with connection vars

[webservers]
web1.example.com ansible_host=10.0.1.10 ansible_user=deploy

2. YAML inventory

all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 10.0.1.10

3. group_vars/all.yml

ansible_user: deploy
ansible_ssh_private_key_file: ~/.ssh/ansible_key

4. host_vars/web1.example.com.yml

ansible_port: 2222

5. ansible.cfg inventory

[defaults]
inventory = inventory/

6. ansible.cfg forks

forks = 20

7. ansible.cfg fact caching

gathering = smart
fact_caching = jsonfile

8. The config search order

ANSIBLE_CONFIG โ†’ ./ansible.cfg โ†’ ~/.ansible.cfg โ†’ /etc/ansible/ansible.cfg

9. The precedence check

ansible-inventory --list -i inventory/

10. The ping test

ansible all -m ping

Visual

The inventory and config relationship

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ansible.cfg                                                 โ”‚
โ”‚    โ”œโ”€โ”€ inventory = inventory/                                โ”‚
โ”‚    โ”œโ”€โ”€ forks = 20                                            โ”‚
โ”‚    โ””โ”€โ”€ become = True                                         โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  inventory/                                                  โ”‚
โ”‚    โ”œโ”€โ”€ hosts.ini                                             โ”‚
โ”‚    โ”œโ”€โ”€ group_vars/                                           โ”‚
โ”‚    โ”‚     โ””โ”€โ”€ all.yml                                         โ”‚
โ”‚    โ””โ”€โ”€ host_vars/                                            โ”‚
โ”‚          โ””โ”€โ”€ web1.example.com.yml                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The variable precedence

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Lowest:  Group vars in inventory                            โ”‚
โ”‚           group_vars/all                                     โ”‚
โ”‚           Child group vars                                   โ”‚
โ”‚           Host vars in inventory                             โ”‚
โ”‚  Highest: host_vars/                                         โ”‚
โ”‚                                                              โ”‚
โ”‚  The later definition wins.                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The config search order

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  1. ANSIBLE_CONFIG (env var)                                 โ”‚
โ”‚  2. ./ansible.cfg                                            โ”‚
โ”‚  3. ~/.ansible.cfg                                           โ”‚
โ”‚  4. /etc/ansible/ansible.cfg                                 โ”‚
โ”‚                                                              โ”‚
โ”‚  The first file found is used.                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The connection variables

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ansible_host โ”€โ”€โ–บ the IP or hostname                         โ”‚
โ”‚  ansible_port โ”€โ”€โ–บ the SSH port                               โ”‚
โ”‚  ansible_user โ”€โ”€โ–บ the SSH user                               โ”‚
โ”‚  ansible_ssh_private_key_file โ”€โ”€โ–บ the key path               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Inventory formatsINI, YAML, dynamic plugin
YAML recommendationConsistent variable typing
Connection variablesansible_host, ansible_port, ansible_user
Variable directoriesgroup_vars/, host_vars/
Variable precedenceHost vars override group vars
Config fileansible.cfg
Config search orderANSIBLE_CONFIG, ./, ~/, /etc/ansible/
Parallelismforks (default 5)
Fact cachinggathering, fact_caching

Key takeaways:

  • The inventory defines the targets and their connection details. The INI format is the legacy format; the YAML format is recommended for new inventories because it handles variable types consistently . The connection variables (ansible_host, ansible_port, ansible_user) override the defaults for each host .
  • The group_vars and host_vars directories organize variables outside the inventory. The group_vars/all file applies to every host, the group_vars/<group> file applies to a group, and the host_vars/<host> file applies to a single host. The more specific definition wins .
  • The ansible.cfg file controls the control node’s behavior. The inventory setting points to the inventory, the forks setting controls parallelism, and the gathering and fact_caching settings control fact collection. The file is searched in a defined order, and the first match wins .
  • The ANSIBLE_CONFIG environment variable overrides all other config locations. It is the mechanism for using a different configuration file for a specific run without modifying the project’s ansible.cfg .
  • The ansible_group_priority variable controls group merge order. A higher number means the group is merged later, giving it higher priority. It can only be set in the inventory source, not in group_vars .
  • The inventory and config are both version-controlled artifacts. The inventory changes between environments, and the config changes between projects. Keeping both in the repository makes the deployment reproducible and reviewable.

Remember: The inventory is the target list, and the ansible.cfg is the behavior list. The inventory defines the hosts, the groups, and the connection variables. The ansible.cfg defines where the inventory lives, how many hosts to manage in parallel, and how facts are gathered. The group_vars and host_vars directories organize the variables that describe each host’s role and configuration. The precedence order determines which value wins when the same setting is defined in more than one place. Get the inventory right first, because a playbook with no targets does nothing. Then tune the ansible.cfg for the fleet size and the network conditions.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!