Ansible Host Groups & Variables

Host grouping and variables are the two features that transform a simple list of servers into a structured, manageable representation of your infrastructure. This lesson teaches you to organise hosts into meaningful groups and attach the right variables to the right hosts — skills that directly affect how clean and maintainable your playbooks will be.

Why Groups Matter

Groups are the primary mechanism for applying tasks selectively. Without groups, every playbook would either run on all hosts or require you to manually specify individual IP addresses. With groups, you write a play that targets webservers and it automatically applies to every current and future host in that group — including new hosts you add to the group months from now.

Good group design mirrors the functional architecture of your infrastructure. Common grouping strategies include:

  • By function: webservers, databases, loadbalancers, monitoring
  • By environment: production, staging, development, testing
  • By geography: us-east, eu-west, ap-southeast
  • By OS: ubuntu, centos, debian

These strategies can be combined. A single host can belong to multiple groups simultaneously — web01 might be in webservers, production, and us-east all at once.

Nested Groups with children

The :children syntax creates parent groups that aggregate child groups:

[webservers]
web01 ansible_host=10.0.1.10
web02 ansible_host=10.0.1.11

[databases]
db01 ansible_host=10.0.2.10

[production:children]
webservers
databases

[staging]
staging-web01 ansible_host=10.1.1.10
staging-db01  ansible_host=10.1.2.10

[all_web:children]
webservers
staging

This structure lets you target the entire production tier with ansible production -m ping, or all web servers across environments with ansible all_web. The nesting can go multiple levels deep for complex multi-region, multi-environment architectures.

Group Variables

Group variables apply to every host in a group. They are the right place to store settings that are consistent across a group but different between groups — for example, the web server port, the database connection string, or the monitoring endpoint URL.

Inline group variables in the inventory file:

[webservers:vars]
http_port=80
max_clients=200
document_root=/var/www/html

[databases:vars]
db_port=5432
backup_enabled=true

Group variables in separate files (recommended for maintainability):

Create a group_vars/ directory alongside your inventory file. Inside, create one YAML file per group, named exactly after the group:

group_vars/
  webservers.yml
  databases.yml
  all.yml

The contents of group_vars/webservers.yml:

http_port: 80
max_clients: 200
document_root: /var/www/html
nginx_worker_processes: auto

Ansible automatically reads these files and makes the variables available to any host in the corresponding group. The separate-file approach keeps the inventory file focused on host definitions and moves complex variable data to dedicated, clearly-named files.

Host Variables

Host variables apply to a single specific host. Use them for settings that are genuinely unique per host — a specific IP binding, a custom port, a host-specific certificate path, or hardware-specific tuning parameters.

Inline in the inventory file:

[webservers]
web01 ansible_host=10.0.1.10 http_port=8080 is_primary=true
web02 ansible_host=10.0.1.11 http_port=80   is_primary=false

In host_vars files (recommended):

host_vars/
  web01.yml
  web02.yml
  db01.yml

Contents of host_vars/web01.yml:

http_port: 8080
is_primary: true
ssl_certificate: /etc/ssl/certs/web01.pem
backup_schedule: "0 2 * * *"

Variable Precedence

When the same variable is defined at multiple levels, Ansible uses a specific precedence order. From lowest to highest priority:

  1. Inventory file [all:vars] — lowest priority
  2. Inventory group variables (group_vars/all.yml)
  3. Specific group variables (group_vars/webservers.yml)
  4. Host variables (host_vars/web01.yml)
  5. Playbook vars: — higher priority
  6. Extra vars (ansible-playbook -e) — highest priority

This hierarchy lets you set sensible defaults at the group level and override them for specific hosts or at runtime without modifying the baseline configuration. For example, set http_port: 80 in group_vars/webservers.yml and override it to 8443 only in host_vars/web01.yml.

Special Connection Variables

Several variable names are reserved by Ansible for controlling how connections are made:

  • ansible_host — The IP or hostname to connect to
  • ansible_port — The SSH port (default: 22)
  • ansible_user — The remote username
  • ansible_ssh_private_key_file — Path to the SSH private key
  • ansible_become — Whether to use privilege escalation (true/false)
  • ansible_become_method — How to escalate (sudo, su, etc.)
  • ansible_python_interpreter — Path to Python on the managed node

These can be set at any level of the variable hierarchy — per host, per group, or globally. Setting ansible_user: ubuntu in group_vars/all.yml means all hosts connect as the ubuntu user unless a more specific variable overrides it.

Try This: Structure Your Lab Inventory with Variables

In your lab directory, create the full directory structure:

inventory/
  hosts.ini
  group_vars/
    all.yml
    webservers.yml
    databases.yml
  host_vars/
    web01.yml

In all.yml, set ansible_user and ansible_ssh_private_key_file. In webservers.yml, set http_port: 80. In host_vars/web01.yml, override http_port: 8080. Then run ansible-inventory -i inventory/ --host web01 and confirm that http_port shows as 8080 for web01 but 80 for web02.

Summary

Host grouping allows selective targeting of playbooks against logical subsets of infrastructure. Group variables apply consistently to all members of a group; host variables override settings for individual hosts. The group_vars/ and host_vars/ directory conventions keep inventory clean and maintainable. Variable precedence rules govern which value wins when the same variable is defined at multiple levels.

Leave a Comment