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 vars_files: Load Variables from External YAML Files (Guide)

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

Complete guide to Ansible vars_files. Load variables from external YAML files, use with Ansible Vault encryption, organize by environment, and handle.

The vars_files directive loads variables from external YAML files into your Ansible playbooks. It keeps playbooks clean, enables variable reuse across plays, and is essential for managing encrypted secrets with Ansible Vault.

Basic Syntax

- hosts: webservers
  vars_files:
    - vars/common.yml
    - vars/webserver.yml
  tasks:
    - name: Use loaded variables
      ansible.builtin.debug:
        msg: "Port: {{ http_port }}, Env: {{ environment }}"
# vars/common.yml
environment: production
log_level: info
company_name: Acme Corp

# vars/webserver.yml http_port: 8080 max_workers: 4 document_root: /var/www/html

See also: Ansible Variable Precedence: Complete Order of Priority (2026)

Multiple Files

List multiple files — they're loaded in order, with later files overriding earlier ones:

- hosts: all
  vars_files:
    - vars/defaults.yml        # Base defaults
    - vars/{{ env }}.yml       # Environment overrides
    - vars/secrets.yml         # Encrypted secrets

Dynamic File Names

Use variables in filenames for environment-specific configs:

- hosts: all
  vars_files:
    - "vars/{{ ansible_os_family }}.yml"
    - "vars/{{ env | default('staging') }}.yml"
# vars/Debian.yml
package_manager: apt
service_manager: systemd

# vars/RedHat.yml package_manager: yum service_manager: systemd

See also: Ansible default() Filter: Set Fallback Values for Undefined Variables

vars_files with Ansible Vault

The most common pattern — keep secrets in encrypted files:

# Create encrypted file
ansible-vault create vars/secrets.yml
# vars/secrets.yml (encrypted)
db_password: "s3cr3t_p4ssw0rd"
api_key: "ak_live_1234567890"
ssl_private_key: |
  -----BEGIN PRIVATE KEY-----
  ...
# playbook.yml
- hosts: webservers
  vars_files:
    - vars/common.yml
    - vars/secrets.yml  # Ansible Vault encrypted
  tasks:
    - name: Configure database
      ansible.builtin.template:
        src: db.conf.j2
        dest: /etc/app/db.conf
        mode: '0600'

Run with vault password:

ansible-playbook playbook.yml --ask-vault-pass
# or
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass

Optional Files (Avoid Errors)

If a file might not exist, use a list-of-lists pattern or include_vars with ignore_errors:

# Method 1: First file that exists wins
- hosts: all
  vars_files:
    - ["vars/{{ ansible_hostname }}.yml", "vars/default.yml"]
    # Tries host-specific file first, falls back to default

# Method 2: Use include_vars in tasks - hosts: all tasks: - name: Load optional overrides ansible.builtin.include_vars: file: "vars/{{ ansible_hostname }}.yml" ignore_errors: true

See also: Ansible register: Save Task Output to Variables (Complete Guide)

vars_files vs Other Variable Methods

| Method | When Loaded | Scope | Dynamic Filenames | Use For | |--------|------------|-------|-------------------|---------| | vars_files | Play start | Play | ✅ | External variable files, vault secrets | | vars: | Play start | Play | N/A (inline) | Small, inline variable sets | | include_vars | Task runtime | Task onwards | ✅ | Conditional loading, dynamic files | | group_vars/ | Inventory parse | Group | ❌ (directory-based) | Environment/group config | | host_vars/ | Inventory parse | Host | ❌ (directory-based) | Host-specific overrides | | defaults/main.yml | Role loading | Role | ❌ | Role default values |

Project Structure Example

project/
├── playbook.yml
├── vars/
│   ├── common.yml          # Shared variables
│   ├── production.yml      # Production overrides
│   ├── staging.yml         # Staging overrides
│   ├── secrets.yml         # Vault-encrypted secrets
│   ├── Debian.yml          # OS-specific variables
│   └── RedHat.yml          # OS-specific variables
├── group_vars/
│   ├── all.yml
│   └── webservers.yml
├── inventory/
└── roles/
# playbook.yml
- hosts: webservers
  vars_files:
    - vars/common.yml
    - "vars/{{ env }}.yml"
    - vars/secrets.yml
  roles:
    - webserver

Precedence

vars_files has the same precedence as vars_prompt (level 14 in Ansible's 22-level hierarchy): • Higher than: group_vars, host_vars, play vars, role defaults • Lower than: role vars, block vars, task vars, set_fact, extra vars

FAQ

What does vars_files do in Ansible?

vars_files loads variables from one or more external YAML files at the beginning of a play. The variables become available to all tasks, roles, and templates within that play.

What is the difference between vars_files and include_vars?

vars_files loads at play start (before any tasks run) and is declared at the play level. include_vars is a task-level module that loads variables at runtime — useful for conditional loading and dynamic filenames based on gathered facts.

Can I use vars_files with Ansible Vault?

Yes, this is the most common pattern. List your vault-encrypted file in vars_files and run the playbook with --ask-vault-pass or --vault-password-file. Ansible decrypts transparently.

What happens if a vars_file doesn't exist?

Ansible throws an error and stops. To handle optional files, use a list-of-lists syntax [preferred.yml, fallback.yml] or use include_vars with ignore_errors: true.

Can I use variables in vars_files paths?

Yes, you can use Jinja2 variables in filenames: vars_files: ["vars/{{ env }}.yml"]. The variable must be defined before vars_files is processed (e.g., via extra vars, inventory vars, or earlier in the list).

Conclusion

vars_files is the cleanest way to externalize playbook variables • Combine with Vault for encrypted secrets • Use dynamic filenames for environment/OS-specific configs • Order matters — later files override earlier ones • Use include_vars when you need runtime conditional loading

Related Articles

Ansible Variable Precedence: Complete GuideAnsible Vault: Encrypt SecretsAnsible Extra Vars: Pass Variables via Command LineAnsible set_fact Module: Dynamic Variables

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home