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 Guide • Ansible Vault: Encrypt Secrets • Ansible Extra Vars: Pass Variables via Command Line • Ansible set_fact Module: Dynamic VariablesCategory: troubleshooting