AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Variables: Complete Guide to vars, facts & Precedence

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible variables. Define vars, use facts, understand precedence, register output, and manage variables across inventories and roles.

Ansible variables are a core feature that allows users to make playbooks dynamic and reusable. By defining variables, you can simplify configurations, adapt tasks to different environments, and manage large-scale automation workflows effectively. This article explores Ansible variables, their types, and best practices for using them.

What Are Ansible Variables?

Ansible variables are key-value pairs that store data used during playbook execution. They make playbooks flexible by allowing you to dynamically configure tasks based on the target system or environment.

Key Features:

Dynamic Customization: Modify task behavior based on variable values. • Centralized Management: Define variables in a single place for easier updates. • Reusability: Share variables across multiple playbooks.

See also: Project Policy Validation with OPA and ansible-policy

Types of Ansible Variables

Ansible supports a variety of variable types to suit different use cases:

1. Playbook Variables

Variables defined directly within a playbook.

Example:

   - name: Install packages
     hosts: all
     vars:
       package_name: nginx
     tasks:
       - name: Install a package
         apt:
           name: "{{ package_name }}"
           state: present
   

2. Host Variables

Variables specific to individual hosts, defined in the inventory file or host-specific files.

Example in Inventory:

   [webservers]
   host1 ansible_host=192.168.1.10 ansible_user=admin app_version=1.2.3
   

Example in host_vars/host1.yml:

   app_version: 1.2.3
   

3. Group Variables

Variables applied to groups of hosts, defined in the inventory file or group-specific files.

Example in group_vars/webservers.yml:

   app_name: my_web_app
   

4. Facts

Automatically gathered variables about the target system.

Example:

   - name: Print operating system
     debug:
       msg: "The OS is {{ ansible_distribution }}"
   

5. Command-Line Variables

Variables passed at runtime using the --extra-vars option.

Example:

   ansible-playbook playbook.yml --extra-vars "user=admin package=nginx"
   

6. Default Variables

Variables with default values defined in roles or playbooks.

Example:

   - name: Install with defaults
     hosts: all
     tasks:
       - name: Install a package
         apt:
           name: "{{ package | default('nginx') }}"
           state: present
   

Precedence of Variables

When multiple variables are defined, Ansible resolves conflicts using a precedence order. The order (from lowest to highest) includes: Defaults in roles. Inventory Group Variables. Inventory Host Variables. Playbook Variables. Extra Variables (always highest precedence).

See also: What Are Ansible Playbooks? Definition, Structure, and Examples (2026 Guide)

Using Variables in Playbooks

Variables can be referenced using {{ variable_name }} syntax.

Example with Loops:

- name: Install multiple packages
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - curl
    - git

Example with Conditionals:

- name: Install only on Debian
  apt:
    name: apache2
    state: present
  when: ansible_os_family == "Debian"

Example with Templates:

Use variables in Jinja2 templates for dynamic configuration files. nginx.conf.j2:
server {
    listen {{ nginx_port }};
    server_name {{ nginx_server_name }};
}

Playbook:

- name: Deploy Nginx configuration
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf

Best Practices for Using Variables

Use Meaningful Names: Avoid ambiguous variable names to ensure clarity. Organize Variables: Store variables in group_vars/ and host_vars/ directories for better structure. Secure Sensitive Data: Use Ansible Vault to encrypt variables like passwords and API keys. Define Defaults: Provide default values to prevent errors in playbook execution. Test Variable Resolution: Use ansible-playbook --check to validate variable substitution.

See also: Where Are Ansible Modules Stored? Location & Path Guide

Conclusion

Ansible variables are a fundamental tool for making playbooks dynamic, reusable, and efficient. By leveraging different types of variables and following best practices, you can simplify complex automation workflows and manage diverse environments effectively.

Learn More About Ansible Variables

Define Variables

In playbook

- hosts: webservers
  vars:
    http_port: 80
    app_name: myapp
    packages:
      - nginx
      - python3
  tasks:
    - debug: msg="Port {{ http_port }}"

In inventory

# group_vars/webservers.yml
http_port: 80
document_root: /var/www/html

# host_vars/web1.yml http_port: 8080

On command line

ansible-playbook site.yml -e "http_port=8080 app_env=production"
ansible-playbook site.yml -e "@vars.yml"

With set_fact (runtime)

- set_fact:
    full_url: "http://{{ ansible_host }}:{{ http_port }}"

Variable Types

# String
name: "myapp"

# Number port: 8080

# Boolean debug_mode: true

# List packages: - nginx - curl - vim

# Dictionary database: host: db.example.com port: 5432 name: myapp

Access Variables

# Simple
msg: "{{ http_port }}"

# Dictionary msg: "{{ database.host }}" msg: "{{ database['host'] }}"

# List msg: "{{ packages[0] }}"

# Nested msg: "{{ servers.web.config.port }}"

Variable Precedence (Low → High)

Role defaults (defaults/main.yml) Inventory group_vars Inventory host_vars Playbook group_vars Playbook host_vars Play vars Role vars (vars/main.yml) Block/task vars set_fact / registered vars Extra vars (-e) — always wins

Register Variables

- command: uptime
  register: uptime_result

- debug: msg: | stdout: {{ uptime_result.stdout }} rc: {{ uptime_result.rc }} changed: {{ uptime_result.changed }}

Default Values

- debug:
    msg: "Port: {{ http_port | default(80) }}"
    
# Required variable (fail if undefined)
- debug:
    msg: "{{ required_var | mandatory }}"

Variable in Conditionals

- name: Install on Debian
  apt: name=nginx
  when: ansible_os_family == "Debian"

- name: Only in production template: src=prod.conf.j2 dest=/etc/app.conf when: app_env == "production"

Encrypted Variables (Vault)

# Encrypt a variable file
ansible-vault encrypt group_vars/production.yml

# Encrypt single value ansible-vault encrypt_string 'SuperSecret123' --name 'db_password'

# Use in playbook
db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  6531326...

Special Variables

| Variable | Description | |----------|-------------| | inventory_hostname | Current host name | | ansible_host | Connection address | | groups | All inventory groups | | hostvars | All host variables | | play_hosts | Hosts in current play | | ansible_facts | Gathered facts | | role_path | Current role path |

FAQ

Why does my variable show as undefined?

Check: 1) Spelling, 2) Scope (defined in wrong play/role), 3) Precedence (overridden by higher priority). Use -e to override everything.

How do I use variables across plays?

Use set_fact with cacheable: true, or access via hostvars[hostname].variable.

Can I use variables in variable names?

Yes, with vars lookup: {{ hostvars[server_name][var_name] }} or {{ lookup('vars', dynamic_name) }}

Define Variables

# In playbook
- hosts: all
  vars:
    app_port: 8080
    db_host: db.internal
  tasks:
    - debug: msg="Port {{ app_port }}"

# In vars file - hosts: all vars_files: - vars/common.yml - "vars/{{ env }}.yml"

Variable Sources

# group_vars/webservers.yml
http_port: 80
ssl_enabled: true

# host_vars/web1.yml custom_setting: "specific to web1"

# Inventory variables [webservers] web1 ansible_host=10.0.1.10 http_port=8080

# Extra vars (highest priority) # ansible-playbook site.yml -e "version=2.5"

Register Variables

- command: hostname -f
  register: hostname_result

- debug: msg: "FQDN: {{ hostname_result.stdout }}"

# Common registered attributes: # .stdout, .stderr, .rc, .changed, .failed # .stdout_lines (list of lines)

set_fact

- set_fact:
    app_url: "https://{{ domain }}:{{ port }}"
    is_production: "{{ env == 'production' }}"
    memory_gb: "{{ ansible_memtotal_mb / 1024 | round(1) }}"

Variable Precedence (Low → High)

1.  command line values (eg "-u user")
2.  role defaults (defaults/main.yml)
3.  inventory file or script group vars
4.  inventory group_vars/all
5.  playbook group_vars/all
6.  inventory group_vars/*
7.  playbook group_vars/*
8.  inventory file or script host vars
9.  inventory host_vars/*
10. playbook host_vars/*
11. host facts / cached set_facts
12. play vars
13. play vars_prompt
14. play vars_files
15. role vars (vars/main.yml)
16. block vars (only for tasks in block)
17. task vars (only for the task)
18. include_vars
19. set_facts / registered vars
20. role params
21. include params
22. extra vars (-e)  ← ALWAYS WINS

Data Types

# String
name: "hello"

# Integer port: 8080

# Boolean enabled: true

# List packages: - nginx - redis - postgresql

# Dictionary database: host: localhost port: 5432 name: mydb

# Nested app: server: port: 8080 workers: 4

Access Nested Variables

# Dot notation
msg: "{{ database.host }}"

# Bracket notation (safer for special chars) msg: "{{ database['host'] }}"

# Nested msg: "{{ app.server.port }}"

Default Values

msg: "{{ my_var | default('fallback') }}"
msg: "{{ my_var | default(omit) }}"  # Skip param if undefined
msg: "{{ my_var | default(false) }}"

Prompt for Variables

- hosts: all
  vars_prompt:
    - name: deploy_version
      prompt: "Which version to deploy?"
      default: "latest"
    - name: db_password
      prompt: "Database password"
      private: true  # Hidden input

Vault Encrypted Variables

# Encrypt a variable
ansible-vault encrypt_string 'SuperSecret' --name 'db_password'
# In vars file
db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  616364...

FAQ

How to check if a variable is defined?

when: my_var is defined
when: my_var is undefined
when: my_var | length > 0

Can I use variables in variable names?

# Yes, with lookup or hostvars
value: "{{ hostvars[inventory_hostname]['custom_' + env + '_setting'] }}"

group_vars vs role defaults?

group_vars for environment-specific values (prod vs staging). Role defaults for sane default values that users can override.

Related Articles

the Ansible template module referencethe Ansible Vault walkthroughconditional execution with Ansible whenAnsible Inventory Guidesubelements lookup with Ansible loops

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home