Skip to main content

Ansible Host Variables

Introduction

When managing multiple servers with Ansible, you'll often need to apply specific configurations to individual hosts. This is where host variables come into play. Host variables allow you to customize how Ansible treats each host in your inventory, making your automation more flexible and powerful.

In this guide, we'll explore how to define host variables in Ansible, understand their scope, and see how they fit into Ansible's variable precedence system. By the end, you'll be able to create more sophisticated playbooks that can adapt to the specific needs of each managed host.

What Are Host Variables?

Host variables are values assigned to specific hosts in your Ansible inventory. They allow you to:

  • Store host-specific data (like IP addresses, port numbers, custom settings)
  • Override default variables for particular hosts
  • Define how Ansible should connect to and interact with each host

Defining Host Variables

There are several ways to define host variables in Ansible. Let's explore each method:

1. Inline Variables in Inventory File

The simplest way to define host variables is directly in your inventory file:

ini
# Simple inventory file with host variables
webserver ansible_host=192.168.1.50 ansible_user=admin http_port=8080
database ansible_host=192.168.1.51 ansible_user=dbadmin db_port=5432

In this example:

  • ansible_host specifies the IP address Ansible will use to connect to the host
  • ansible_user defines which user Ansible will use for SSH connections
  • http_port and db_port are custom variables we've defined

2. Variables in INI-format Inventory

For better readability, you can define variables using brackets:

ini
[webservers]
web1.example.com
web2.example.com

[webservers:vars]
http_port=80
max_connections=1000

[databases]
db1.example.com
db2.example.com

[databases:vars]
db_port=5432
backup_enabled=true

[all:vars]
ansible_user=devops

Here, we've defined:

  • Group variables for all webservers and databases
  • Global variables for all hosts using [all:vars]

3. Variables in YAML Inventory

If you prefer YAML, you can define variables like this:

yaml
all:
hosts:
web1:
ansible_host: 192.168.1.100
http_port: 80
max_requests: 1000
db1:
ansible_host: 192.168.1.101
db_port: 5432
backup_time: "03:00"
children:
webservers:
hosts:
web1:
databases:
hosts:
db1:

4. Host Variable Files

For complex setups, Ansible allows you to store host variables in separate YAML files. This is the most scalable approach:

  1. Create a directory structure:

    inventory/
    ├── hosts.yml
    ├��─ host_vars/
    │ ├── web1.yml
    │ └── db1.yml
    └── group_vars/
    ├── webservers.yml
    └── databases.yml
  2. Define variables in the files:

    File: inventory/host_vars/web1.yml

    yaml
    ---
    ansible_host: 192.168.1.100
    ansible_user: webadmin
    http_port: 80
    app_env: production
    memory_limit: 2G
    enable_ssl: true
    ssl_cert_path: "/etc/ssl/certs/web1.crt"

    File: inventory/host_vars/db1.yml

    yaml
    ---
    ansible_host: 192.168.1.101
    ansible_user: dbadmin
    db_port: 5432
    db_version: "14"
    backup_schedule: "0 2 * * *"
    replication_enabled: true
    max_connections: 200

This approach keeps your inventory file clean while allowing complex variable configurations.

Special Ansible Connection Variables

Ansible has several built-in host variables that control how it connects to hosts:

VariableDescriptionExample
ansible_hostThe hostname or IP to connect toansible_host=192.168.1.50
ansible_portThe SSH port to useansible_port=2222
ansible_userThe username for SSH connectionsansible_user=admin
ansible_passwordThe password for SSH connections (use vault for security)ansible_password=secret
ansible_connectionConnection type to useansible_connection=ssh
ansible_ssh_private_key_fileSSH private key fileansible_ssh_private_key_file=/path/to/key
ansible_becomeWhether to use privilege escalationansible_become=yes
ansible_become_methodMethod for privilege escalationansible_become_method=sudo
ansible_become_userUser to becomeansible_become_user=root

Using Host Variables in Playbooks

Once defined, you can use host variables in your playbooks using Jinja2 templating:

yaml
---
- name: Configure web servers
hosts: webservers
tasks:
- name: Set up web server port
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
vars:
server_port: "{{ http_port | default(80) }}"

- name: Start web service
service:
name: httpd
state: started
enabled: yes

In this playbook, {{ http_port | default(80) }} uses the http_port variable if defined for the host, or falls back to port 80.

Practical Example: Multi-Environment Deployment

Let's see a real-world example of using host variables to deploy an application across different environments:

  1. Define your inventory with host variables:

    File: inventory/hosts.yml

    yaml
    all:
    children:
    production:
    hosts:
    prod-web1:
    prod-web2:
    prod-db1:
    staging:
    hosts:
    stage-web1:
    stage-db1:
    development:
    hosts:
    dev-web1:
    dev-db1:
  2. Create host variable files:

    File: inventory/host_vars/prod-web1.yml

    yaml
    ansible_host: 192.168.10.10
    env: production
    memory_limit: 4G
    app_debug: false
    app_domain: example.com

    File: inventory/host_vars/stage-web1.yml

    yaml
    ansible_host: 192.168.20.10
    env: staging
    memory_limit: 2G
    app_debug: true
    app_domain: staging.example.com
  3. Create a deployment playbook:

    yaml
    ---
    - name: Deploy application
    hosts: all
    tasks:
    - name: Display environment information
    debug:
    msg: "Deploying to {{ env }} environment on {{ inventory_hostname }}"

    - name: Generate configuration file
    template:
    src: app-config.j2
    dest: /var/www/app/config.php
    vars:
    debug_mode: "{{ app_debug | default(false) }}"
    site_domain: "{{ app_domain }}"
    mem_limit: "{{ memory_limit | default('1G') }}"
  4. Create the template file:

    File: templates/app-config.j2

    php
    <?php
    // Configuration generated by Ansible
    // Environment: {{ env }}

    return [
    'debug' => {{ debug_mode | lower }},
    'domain' => '{{ site_domain }}',
    'memory_limit' => '{{ mem_limit }}',
    'environment' => '{{ env }}',
    'generated_at' => '{{ ansible_date_time.iso8601 }}',
    ];

When you run this playbook, Ansible will automatically use the appropriate host variables for each server, allowing you to deploy to multiple environments with a single playbook.

Variable Precedence

It's important to understand that Ansible has a specific order of variable precedence. For example, variables set in a playbook will override those in the inventory. The general rule is that variables defined closer to the task execution have higher precedence.

Here's a simplified precedence order (from lowest to highest):

  1. Default variables defined in roles
  2. Inventory variables (group_vars/all)
  3. Inventory group variables (group_vars/groupname)
  4. Inventory host variables (host_vars/hostname)
  5. Playbook group_vars/all
  6. Playbook group_vars/groupname
  7. Playbook host_vars/hostname
  8. Host facts
  9. Play variables (vars: section)
  10. Task variables (vars: section)
  11. Extra variables (-e option in command line)

Best Practices for Host Variables

  1. Keep sensitive data encrypted Use Ansible Vault to encrypt sensitive host variables like passwords:

    bash
    ansible-vault encrypt inventory/host_vars/web1.yml
  2. Use a clear directory structure Organize your variables with a consistent structure:

    inventory/
    ├── hosts.yml
    ├── host_vars/ # Host-specific variables
    └── group_vars/ # Group-specific variables
  3. Document your variables Add comments in your variable files to explain what each variable is for:

    yaml
    ---
    # Maximum number of simultaneous connections
    # Increase this value for high-traffic servers
    max_connections: 1000
  4. Use defaults wisely Provide default values in your templates or playbooks:

    yaml
    server_port: "{{ http_port | default(80) }}"
  5. Avoid variable name collisions Consider using prefixes for your variables to avoid conflicts:

    yaml
    app_port: 8080
    db_port: 5432

Debugging Host Variables

To check what variables are defined for a host, use the ansible-inventory command:

bash
# List all variables for a specific host
ansible-inventory --host web1 --yaml

# Show the entire inventory with all variables
ansible-inventory --list --yaml

You can also use the debug module in a playbook to inspect variables:

yaml
---
- name: Debug host variables
hosts: web1
tasks:
- name: Display all variables
debug:
var: hostvars[inventory_hostname]

- name: Display specific variable
debug:
var: http_port

Summary

Host variables are a powerful feature in Ansible that allow you to customize configurations for individual hosts in your inventory. By properly utilizing host variables, you can:

  • Create more flexible and reusable playbooks
  • Manage different environments with the same code
  • Customize connections to each host
  • Organize your automation in a scalable way

Remember that you can define host variables in multiple ways: inline in the inventory, in group variables, or in dedicated variable files. Choose the approach that best fits your needs and the complexity of your infrastructure.

Exercises

  1. Create an inventory with at least three hosts and define different host variables for each.
  2. Write a playbook that uses these host variables to generate different configuration files.
  3. Experiment with variable precedence by defining the same variable at different levels.
  4. Use Ansible Vault to encrypt sensitive host variables.
  5. Create a playbook that displays all the variables for a specific host.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)