unit 3 · Inventory

group_vars & host_vars

Config files that find their hosts by name

essential · 6 min · linux + windows

you may want to read 8 · Inventory: INI and YAML first — but nothing is locked

tl;dr

  • group_vars/ and host_vars/ sit next to your inventory and auto-load by group and host name.
  • Environment config lives here — per group in group_vars, pinned to one machine in host_vars.
  • group_vars/all.yml hits every host in the inventory. Keep it minimal.

why it matters Every real repo carries these directories. If you don’t know the files load themselves by name, you’ll hunt for an import that doesn’t exist — and put environment config in all the wrong places.

Lesson 8 gave you groups. This lesson gives them configuration, through two directories next to your inventory file: group_vars and host_vars . The entire trick is in the filenames:

inventory/
├── hosts.yml           # your lesson-8 inventory: web, db, all the groups
├── group_vars/
│   ├── all.yml         # every host in the inventory — keep it minimal
│   └── web.yml         # every host in the web group
└── host_vars/
    └── web01.yml       # exactly one machine: web01
Nothing references these files anywhere. The names do all the work.

No import line, no path setting, no reference from the inventory. Ansible auto-loads each file by matching its name against your group and host names. group_vars/web.yml applies to every host in web; host_vars/web01.yml to the single host web01. group_vars/all.yml applies to everything, because every host belongs to the built-in all group. A vars file is just YAML keys and values:

# loaded automatically for every host in the web group
app_env: staging
http_port: 8080
motd_message: 'managed by ansible - do not hand-edit'
group_vars/web.yml — no boilerplate, just values

Where environment config lives

The rule is blunt: environment config lives here. Ports, service endpoints, tuning values — anything that varies between staging and production belongs in group_vars. Not hardcoded into a playbook, not scattered across the inventory file. When roles arrive in Unit 6, you’ll see the full division of labour: user-tunable defaults in the role, environment values in group_vars.

Two habits separate tidy repos from haunted ones:

  • Keep group_vars/all.yml minimal. A value there touches every host in the inventory, so it must be genuinely universal. Environment-specific values belong in the environment’s own inventory directory — more on that below.
  • Use host_vars/ sparingly, for values true of one machine only. If you’re writing the same key into three host files, those hosts want to be a group.

Your inventory now says who your hosts are and what is true about them, all loaded by naming convention. Real repos go one step further: a separate inventory directory per environment (inventories/production/, inventories/staging/), each with its own group_vars and host_vars. So staging values can never bleed into prod. The structure — plus the patterns that pick which hosts a run touches — is lesson 10.

self-check — recall, not a test

  1. 1 You create group_vars/web.yml. What do you have to add elsewhere so Ansible loads it?

  2. 2 An NTP server address differs between staging and production. Where does it belong?

  3. 3 Your group_vars value isn’t the one showing up at runtime. What do you know so far, and where’s the full answer?

lab (optional — never required)

Rebuild this lesson’s tree next to your lesson-8 inventory, then prove the values load with an ad-hoc ansible.builtin.debug call against the web group.

needs: The control node and inventory from lessons 5–8.

next up 10 · Patterns, --limit & per-env inventories 7 min · unit 3