Ansible Variables: Define, Use, and Override Variables (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to use Ansible variables in playbooks, inventory, roles, and command line. Variable types, precedence, register, set_fact, extra vars, vault encryption.
Ansible Variables: Define, Use, and Override Variables (Complete Guide)
Variables are the backbone of flexible Ansible playbooks. Define them in inventory, playbooks, roles, files, or the command line — then reference them anywhere with {{ variable_name }}.
See also: Ansible Playbook: Write and Run Your First Playbook (Complete Guide)
Define Variables
In a Playbook
- hosts: webservers
vars:
http_port: 80
app_name: mywebapp
packages:
- nginx
- python3
- redis
database:
host: db.example.com
port: 5432
name: appdb
tasks:
- name: Show app config
ansible.builtin.debug:
msg: "{{ app_name }} on port {{ http_port }}, DB: {{ database.host }}:{{ database.port }}"
In Variable Files
# vars/production.yml
http_port: 443
ssl_enabled: true
app_replicas: 3
- hosts: webservers
vars_files:
- vars/common.yml
- "vars/{{ env }}.yml"
In Inventory
# inventory.ini
[webservers]
web01 ansible_host=10.0.0.1 http_port=8080
web02 ansible_host=10.0.0.2
[webservers:vars]
app_name=mywebapp
env=production
[all:vars]
ansible_user=deploy
In Group/Host Vars Directories
inventory/
├── hosts.ini
├── group_vars/
│ ├── all.yml # All hosts
│ ├── webservers.yml # Webserver group
│ └── databases.yml # Database group
└── host_vars/
├── web01.yml # Specific host
└── db01.yml
From Command Line (Extra Vars)
# String variable
ansible-playbook site.yml -e "app_version=2.1.0"
# Multiple variables
ansible-playbook site.yml -e "app_version=2.1.0 env=staging"
# JSON
ansible-playbook site.yml -e '{"app_version": "2.1.0", "debug": true}'
# From file
ansible-playbook site.yml -e @vars/deploy.yml
Extra vars (-e) have the highest precedence — they override everything.
Register Variables
Capture task output for use in later tasks.
- name: Check if app is running
ansible.builtin.command: systemctl is-active myapp
register: app_status
ignore_errors: true
changed_when: false
- name: Start app if not running
ansible.builtin.service:
name: myapp
state: started
when: app_status.rc != 0
- name: Show status
ansible.builtin.debug:
msg: "App status: {{ app_status.stdout }}"
Common Register Fields
result.stdout # Standard output (string)
result.stdout_lines # Output as list of lines
result.stderr # Standard error
result.rc # Return code
result.changed # Whether task made changes
result.failed # Whether task failed
result.skipped # Whether task was skipped
See also: Configuring Ansible for VMware: Complete Setup Guide & Playbook
set_fact — Runtime Variables
- name: Calculate config values
ansible.builtin.set_fact:
worker_count: "{{ ansible_processor_vcpus * 2 }}"
cache_size: "{{ (ansible_memtotal_mb * 0.25) | int }}m"
deploy_timestamp: "{{ ansible_date_time.iso8601 }}"
- name: Use calculated values
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
Variable Precedence (Low → High)
Command line values (-u, etc.)
Role defaults (roles/x/defaults/main.yml)
Inventory file group vars
Inventory group_vars/all
Inventory group_vars/
Inventory file host vars
Inventory host_vars/
Host facts / registered vars
Play vars:
Play vars_prompt:
Play vars_files:
Role vars (roles/x/vars/main.yml)
Block vars
Task vars
include_vars
set_fact / registered vars
Role params
include params
Extra vars (-e) ← highest
See also: Creating Custom Ansible Plugins to Fetch API Data Easily
Variable Data Types
vars:
# String
app_name: "myapp"
# Integer
http_port: 8080
# Boolean
ssl_enabled: true
# List
packages:
- nginx
- redis
- postgresql
# Dictionary
database:
host: db.example.com
port: 5432
name: appdb
# Multi-line string
welcome_message: |
Welcome to {{ app_name }}
Running on {{ ansible_hostname }}
Access Variables
# Simple
"{{ app_name }}"
# Dictionary (dot notation)
"{{ database.host }}"
# Dictionary (bracket notation — safer for special chars)
"{{ database['host'] }}"
# List by index
"{{ packages[0] }}"
# Default value if undefined
"{{ optional_var | default('fallback') }}"
# Mandatory (fail if undefined)
"{{ required_var | mandatory }}"
Variable Filters
# String manipulation
"{{ name | upper }}" # MYAPP
"{{ name | lower }}" # myapp
"{{ name | capitalize }}" # Myapp
"{{ name | replace('-','_') }}" # my_app
# Math
"{{ port | int + 1000 }}" # 9080
"{{ size | float }}" # 1024.0
# Lists
"{{ packages | length }}" # 3
"{{ packages | join(',') }}" # nginx,redis,postgresql
"{{ packages | first }}" # nginx
"{{ packages | sort }}" # sorted list
# Defaults
"{{ var | default(omit) }}" # Skip parameter if undefined
Encrypted Variables (Vault)
# Encrypt a variable file
ansible-vault encrypt vars/secrets.yml
# Encrypt a string
ansible-vault encrypt_string 'SuperSecret123' --name 'vault_db_password'
# Use encrypted variables like any other
vars_files:
- vars/secrets.yml
tasks:
- name: Configure database
ansible.builtin.template:
src: db.conf.j2
dest: /etc/myapp/db.conf
# vault_db_password is decrypted automatically
FAQ
How do I define variables in Ansible?
Define variables in playbook vars: section, vars_files:, inventory files, group_vars/ and host_vars/ directories, role defaults/vars, or via -e on the command line. Each location has different precedence.
What is Ansible variable precedence?
Ansible has 22 levels of variable precedence. Extra vars (-e) have the highest. Role defaults have the lowest. The most common override order: role defaults < inventory < playbook vars < set_fact < extra vars.
How do I use registered variables in Ansible?
Use register: varname on a task to capture its output. Access fields like varname.stdout, varname.rc, varname.changed. Use in conditionals: when: varname.rc == 0.
What is the difference between vars and set_fact?
vars are defined at play/task level and scoped to that context. set_fact creates variables at runtime that persist for the host across plays. set_fact can use values from previous tasks.
How do I set a default value for a variable?
Use the default filter: {{ my_var | default('fallback_value') }}. Use default(omit) to skip an optional module parameter when the variable is undefined.
Conclusion
Variables make Ansible playbooks flexible and reusable. Understand the precedence order, use group_vars and host_vars for inventory-specific values, and encrypt sensitive data with Vault.
Related Articles
• Ansible Variable Precedence: Complete Order • Ansible set_fact: Create Runtime Variables • Ansible Vault: Encrypt Sensitive Data • Ansible Extra Vars: Override Variables from CLICategory: troubleshooting