To combine common and specific variables in Ansible, leverage the built-in variable precedence system by defining shared defaults in group or host inventory files, then overriding them with more specific variables in playbooks, roles, or via command-line extra vars. This hierarchy ensures that generic configurations apply broadly while allowing targeted adjustments for individual hosts or environments without duplicating code.
Understanding Variable Precedence
Ansible resolves variable conflicts using a strict precedence order. When you define the same variable name in multiple locations, the value from the highest-precedence source wins. Understanding this order is critical for managing complex infrastructure where some servers require unique settings while others share a baseline configuration.
The general rule is that later definitions override earlier ones. For example, if you set
http_port to 80 in a global defaults file, but set it to 8080 in a playbook task, the playbook value will be used. This allows you to maintain a single source of truth for common settings while retaining flexibility for specific needs.
Defining Common Variables
Common variables should be defined at the lowest possible level of specificity to ensure they apply across your entire infrastructure or large segments of it. The most effective places to store these are within your inventory files or role defaults.
Using the inventory directory structure, you can create
group_vars/ and
host_vars/ directories. Files inside
group_vars/all.yml apply to every host in your inventory. This is ideal for setting base operating system parameters, default package versions, or common user accounts. If you have a subset of servers that share similar traits, such as all web servers, you can create
group_vars/webservers.yml to define variables specific to that group.
Alternatively, when building reusable roles, place common fallback values in the
defaults/main.yml file of the role. These variables are low precedence, meaning they can be easily overridden by higher-level definitions in the playbook or inventory. This approach promotes modularity and makes your roles easier to test and reuse across different projects.
For those needing to manage connections through intermediate hosts, see
Using Ansible: Local Connection with Jump SSH for related networking contexts.
Overriding with Specific Variables
Specific variables are used to customize behavior for individual hosts or specific plays. These overrides must be placed in sources with higher precedence than the common variables.
Host-specific overrides are best stored in
host_vars/.yml. For instance, if one database server requires a larger memory allocation than others, you can define
db_memory_mb: 8192 in its specific host variable file. This value will automatically take precedence over any
db_memory_mb defined in
group_vars/databases.yml.
You can also override variables directly within a playbook using the
vars section. This is useful for temporary changes or for passing data dynamically between tasks. Additionally, command-line arguments like
--extra-vars provide the highest precedence among standard methods, allowing you to inject specific values during execution without modifying any files on disk.
Best Practices for Organization
Maintaining clarity in your variable management prevents unexpected behavior. Start by identifying which variables are truly common and which are likely to change per host. Move stable, shared values to
group_vars or role
defaults, and keep dynamic or unique values in
host_vars or playbook-specific scopes.
Avoid hardcoding values directly in tasks whenever possible. Instead, use variables to make your playbooks adaptable. If you find yourself copying and pasting similar blocks of code with only slight differences, consider refactoring into roles with well-defined input variables. This not only simplifies maintenance but also makes troubleshooting easier, as you know exactly where to look for configuration overrides.
For deeper insights into configuring system services, refer to
Persistently configure the OpenSSH daemon on Linux to understand how service-level settings interact with automation tools.
Frequently Asked Questions
Which takes precedence: group_vars or host_vars?
Host variables always take precedence over group variables. If you define a variable in both
group_vars/all.yml and
host_vars/myhost.yml, the value in the host file will be used. This design allows you to set broad defaults while easily customizing individual machines.
Can I override variables from the command line?
Yes, using
--extra-vars (or
-e) provides the highest precedence among standard CLI options. This method is ideal for CI/CD pipelines or ad-hoc testing where you need to inject specific values without altering repository files. Remember that extra vars can override almost any other variable source except facts and certain internal Ansible variables.
How do I debug variable resolution issues?
Use the
debug module to print the current value of a variable during playbook execution. You can also run
ansible-inventory --list to see how Ansible has merged your inventory variables. This helps identify if an unexpected source is overriding your intended configuration.
What happens if I define the same variable in role defaults and playbook vars?
Playbook variables generally take precedence over role defaults. Role defaults are designed to be flexible fallbacks, so they sit lower in the precedence hierarchy. If you want to enforce a specific value regardless of role defaults, define it in the playbook's
vars section or in
group_vars.