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:
# 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 hostansible_user
defines which user Ansible will use for SSH connectionshttp_port
anddb_port
are custom variables we've defined
2. Variables in INI-format Inventory
For better readability, you can define variables using brackets:
[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:
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:
-
Create a directory structure:
inventory/
├── hosts.yml
├��─ host_vars/
│ ├── web1.yml
│ └── db1.yml
└── group_vars/
├── webservers.yml
└── databases.yml -
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:
Variable | Description | Example |
---|---|---|
ansible_host | The hostname or IP to connect to | ansible_host=192.168.1.50 |
ansible_port | The SSH port to use | ansible_port=2222 |
ansible_user | The username for SSH connections | ansible_user=admin |
ansible_password | The password for SSH connections (use vault for security) | ansible_password=secret |
ansible_connection | Connection type to use | ansible_connection=ssh |
ansible_ssh_private_key_file | SSH private key file | ansible_ssh_private_key_file=/path/to/key |
ansible_become | Whether to use privilege escalation | ansible_become=yes |
ansible_become_method | Method for privilege escalation | ansible_become_method=sudo |
ansible_become_user | User to become | ansible_become_user=root |
Using Host Variables in Playbooks
Once defined, you can use host variables in your playbooks using Jinja2 templating:
---
- 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:
-
Define your inventory with host variables:
File:
inventory/hosts.yml
yamlall:
children:
production:
hosts:
prod-web1:
prod-web2:
prod-db1:
staging:
hosts:
stage-web1:
stage-db1:
development:
hosts:
dev-web1:
dev-db1: -
Create host variable files:
File:
inventory/host_vars/prod-web1.yml
yamlansible_host: 192.168.10.10
env: production
memory_limit: 4G
app_debug: false
app_domain: example.comFile:
inventory/host_vars/stage-web1.yml
yamlansible_host: 192.168.20.10
env: staging
memory_limit: 2G
app_debug: true
app_domain: staging.example.com -
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') }}" -
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):
- Default variables defined in roles
- Inventory variables (group_vars/all)
- Inventory group variables (group_vars/groupname)
- Inventory host variables (host_vars/hostname)
- Playbook group_vars/all
- Playbook group_vars/groupname
- Playbook host_vars/hostname
- Host facts
- Play variables (vars: section)
- Task variables (vars: section)
- Extra variables (-e option in command line)
Best Practices for Host Variables
-
Keep sensitive data encrypted Use Ansible Vault to encrypt sensitive host variables like passwords:
bashansible-vault encrypt inventory/host_vars/web1.yml
-
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 -
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 -
Use defaults wisely Provide default values in your templates or playbooks:
yamlserver_port: "{{ http_port | default(80) }}"
-
Avoid variable name collisions Consider using prefixes for your variables to avoid conflicts:
yamlapp_port: 8080
db_port: 5432
Debugging Host Variables
To check what variables are defined for a host, use the ansible-inventory
command:
# 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:
---
- 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
- Create an inventory with at least three hosts and define different host variables for each.
- Write a playbook that uses these host variables to generate different configuration files.
- Experiment with variable precedence by defining the same variable at different levels.
- Use Ansible Vault to encrypt sensitive host variables.
- 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! :)