Ansible Directory Structure Explained: Defaults vs Vars (Best Practices & Examples)

Ansible Directory Structure: Defaults vs Vars Explained

Ansible is one of the most prominent tools among DevOps for managing software configuration because of its ease of use and bare minimum dependencies. The highlight of this tool is Ansible roles which provide a wholesome package of various functionalities that we need for software configuration.

As we know that ansible roles have a wide directory structure that looks something like this.

$ tree -d
.
├── defaults
├── files
├── handlers
├── media
├── meta
├── molecule
│   └── default
│       └── tests
├── tasks
└── templates

10 directories

We can read online about the significance of these directories but often there is some confusion around two of them that always bugs me, which are vars and defaults. Whenever I write a role I often think of whether to put my variables in defaults or the vars

[ Also Read: How to Activate Virtual Environment in Python VS Code ]

  • Defaults vs Vars in Ansible: What’s the Difference?

    According to official Ansible documentation:

    • defaults → contain default variables for the role

    • vars → contain other role-specific variables

    Key Difference: Variable Precedence

    Variables in vars have higher precedence than variables in defaults.

    Example:
    If a variable version appears in both directories:

    • defaults: version: 5.0.1

    • vars: version: 7.1.3

    The final value used by Ansible will be 7.1.3 (from vars).

Due to my limited understanding of this, I used to define all variables in defaults and whenever needed to override them, I declared those variables in vars.

But There’s More: Static vs Dynamic Variables

Understanding precedence is only part of the story. Through practical usage, we also categorize variables by their nature:

1. Static Variables (Constant Values)

Use defaults/ for:

  • Values that rarely change

  • Role-wide constants

  • Base URLs, paths, or fixed configurations

2. Dynamic Variables (Frequently Changing)

Use vars/ for:

  • Values likely to be customized per environment

  • Versions

  • Instance sizes

  • User-driven inputs

Practical Example: Tomcat Download URL

Suppose the Tomcat download URL is:

“https://archive.apache.org/dist/tomcat/tomcat-version/”

Breakdown:

  • Static part"https://archive.apache.org/dist/tomcat/tomcat-"

  • Dynamic part"version"

Here, we can make a variable for the fixed value in the defaults with any name suppose “tomcat_base_url” and varying value should be declared in vars, let it be with any name suppose “tomcat-version”.

So, whenever I have to use the tomcat download url in the role it will be: “{{ tomcat_base_url }}/{{ tomcat-version }}”.

defaults: contain variables which user have to not alter.

vars: contain variables that require input by user.

Best Practice Summary

Directory Purpose Best Use Case
defaults/ Low-priority static variables Constants, base URLs, default configurations
vars/ High-priority dynamic variables Versions, environment-specific inputs

A simple rule to follow:

  • defaults = values users should NOT frequently change
  • vars = values users will likely override

This structure keeps your Ansible roles maintainable, predictable, and easy for others to customize.

Conclusion

Understanding when to use defaults vs vars in Ansible roles is crucial for clean, scalable configuration management. Using static variables in defaults and dynamic variables in vars ensures consistency and makes roles easier for end users to customize.

If you feel I missed any important points or have more questions about variable precedence or Ansible best practices—drop a comment. Happy Automating!

Source: https://docs.ansible.com/projects/ansible/latest/getting_started/index.html

Related Searches – Cloud Engineering ServicesData Engineering ServicesGenerative AI Solutions

8 thoughts on “Ansible Directory Structure Explained: Defaults vs Vars (Best Practices & Examples)”

  1. “defaults: contain variables which user have to not alter.

    vars: contain variables that require input by user.”

    Now that is something that I can work with. Thanks! 🙂

    1. Given some comments else, mostly around role and variable precedence, I’ll reverse the above, and go with:

      “vars: contain variables which user have to not alter.

      default: contain variables that (may) require (overriding) input by user.”

      The difference here (and triggering the reversal) is that role vars actually have a higher precedence than play vars, and are difficult to override (via a -e on the command line!). So the defaults have sensible defaults and can be easily overridden. So consider the var variables as static, and the default vars to be changeable (dynamic).

      Hope this clears things up and makes sense.

  2. > default: contain variables that (may) require (overriding) input by user.
    Variables from default are always overriden if there are any other out there for example in the following `vars` folder or `host_vars` or `group_vars` or finally in `-e` parameter. But that doesn’t matter that they are dynamic. It proves that they are static. So this takes as to point where defaults because they are on beginning ,they define “static” variables and can be whole variables or just piece of variables that can be appended by other from different directories depends how you wanna organise them. But defaults by default as the name says itself.. they are those that come first and are the static ones.

  3. I think this article is completely wrong. The [Ansible docs](https://docs.ansible.com/ansible/2.9/user_guide/playbooks_variables.html) state about `defaults`:

    > If you are writing a redistributable role with reasonable defaults, put those in the roles/x/defaults/main.yml file. This means the role will bring along a default value but ANYTHING in Ansible will override it.

    And about `vars`:

    > If you are writing a role and want to ensure the value in the role is absolutely used in that role, and is not going to be overridden by inventory, you should put it in roles/x/vars/main.yml

    Therefore, the constant (described as “fixed part” in the article) should go in `vars` while the changeable part (described as “varying part” in the article) should go in `defaults`.

  4. You have this exactly backwards.

    Direct quotes from the ansible doc, “Using Variables”, specifically, “Tips on where to set variables” https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#using-variables

    “Set defaults in roles to avoid undefined-variable errors. If you share your roles, other users can rely on the reasonable defaults you added in the roles/x/defaults/main.yml file, or they can easily override those values in inventory or at the command line.”

    They’ve left out that defaults have the least priority and can be overridden by everything. Recall that in any typical programming language, static variables are exactly that – static. Static variables are the most difficult to override, not the easiest.

    The ansible doc goes on to say – “Set variables [vars] in roles to ensure a value is used in that role, and is not overridden by inventory variables. …. If you are sharing roles with others, putting variables here makes them harder to override, although they still can by passing a parameter to the role or setting a variable with -e.”

    The documentation for this section concludes with an example of a variable defined in vars with the comment, “# this will absolutely be used in this role”. They then give an example of overriding a default variable from a playbook.

    When searching “ansible defaults versus vars”, this article is the first item found, even above Ansible’s own documentation. Please consider updating the information based on the feedback you’ve received.

Leave a Reply