{"id":2567,"date":"2020-03-24T15:35:43","date_gmt":"2020-03-24T10:05:43","guid":{"rendered":"https:\/\/opstree.com\/blog\/\/?p=2567"},"modified":"2026-03-05T17:28:53","modified_gmt":"2026-03-05T11:58:53","slug":"ansible-directory-structure-default-vs-vars","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2020\/03\/24\/ansible-directory-structure-default-vs-vars\/","title":{"rendered":"Ansible Directory Structure Explained: Defaults vs Vars (Best Practices &#038; Examples)"},"content":{"rendered":"\r\n<p>Distinguishing between defaults and variables is an important design decision when developing an <a href=\"https:\/\/opstree.com\/blog\/2022\/10\/18\/understanding-ansible-helm-diff-plugin\/\">Ansible<\/a> role. Defaults serve as your public interface, providing suitable values \u200b\u200bthat users can modify according to their needs. Variables, on the other hand, represent your internal framework, containing constants that must remain constant for the role to function effectively.\u00a0 Striking the right balance not only makes your role user-friendly, but also ensures that it&#8217;s flexible and clearly states what can be customized. A key point is this: use default values \u200b\u200bfor values \u200b\u200bthat users can change, and reserve variables for the role&#8217;s internal needs.<\/p>\r\n<p><!--more--><\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>$ tree -d\r\n.\r\n\u251c\u2500\u2500 defaults\r\n\u251c\u2500\u2500 files\r\n\u251c\u2500\u2500 handlers\r\n\u251c\u2500\u2500 media\r\n\u251c\u2500\u2500 meta\r\n\u251c\u2500\u2500 molecule\r\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 default\r\n\u2502\u00a0\u00a0     \u2514\u2500\u2500 tests\r\n\u251c\u2500\u2500 tasks\r\n\u2514\u2500\u2500 templates\r\n\r\n10 directories<\/code><\/pre>\r\n\r\n\r\n\r\n<p>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 <strong>vars<\/strong> and <strong>defaults<\/strong>. Whenever I write a role I often think of whether to put my variables in <strong>defaults<\/strong> or the <strong>vars<\/strong>.\u00a0<\/p>\r\n<p><strong>[ Also Read: <a href=\"https:\/\/opstree.com\/blog\/2024\/11\/29\/how-to-activate-virtual-environment-in-python-vs-co\" target=\"_blank\" rel=\"noopener\">How to Activate Virtual Environment in Python VS Code<\/a> ]<\/strong><\/p>\r\n\r\n\r\n\r\n<ul>\r\n<li>\r\n<h2 data-start=\"1899\" data-end=\"1957\"><strong data-start=\"1902\" data-end=\"1957\">Defaults vs Vars in Ansible: What\u2019s the Difference?<\/strong><\/h2>\r\n<p data-start=\"1959\" data-end=\"2003\">According to official Ansible documentation:<\/p>\r\n<ul data-start=\"2005\" data-end=\"2117\">\r\n<li data-start=\"2005\" data-end=\"2064\">\r\n<p data-start=\"2007\" data-end=\"2064\"><strong data-start=\"2007\" data-end=\"2019\">defaults<\/strong> \u2192 contain <em data-start=\"2030\" data-end=\"2049\">default variables<\/em> for the role<\/p>\r\n<\/li>\r\n<li data-start=\"2065\" data-end=\"2117\">\r\n<p data-start=\"2067\" data-end=\"2117\"><strong data-start=\"2067\" data-end=\"2075\">vars<\/strong> \u2192 contain <em data-start=\"2086\" data-end=\"2117\">other role-specific variables<\/em><\/p>\r\n<\/li>\r\n<\/ul>\r\n<h2 data-start=\"2119\" data-end=\"2164\"><strong data-start=\"2123\" data-end=\"2162\">Key Difference: Variable Precedence<\/strong><\/h2>\r\n<p data-start=\"2165\" data-end=\"2245\">Variables in <strong data-start=\"2178\" data-end=\"2186\">vars<\/strong> have <strong data-start=\"2192\" data-end=\"2213\">higher precedence<\/strong> than variables in <strong data-start=\"2232\" data-end=\"2244\">defaults<\/strong>.<\/p>\r\n<p data-start=\"2247\" data-end=\"2314\"><strong data-start=\"2247\" data-end=\"2259\">Example:<\/strong><br data-start=\"2259\" data-end=\"2262\" \/>If a variable <code data-start=\"2276\" data-end=\"2285\">version<\/code> appears in both directories:<\/p>\r\n<ul data-start=\"2316\" data-end=\"2373\">\r\n<li data-start=\"2316\" data-end=\"2346\">\r\n<p data-start=\"2318\" data-end=\"2346\">defaults: <code data-start=\"2328\" data-end=\"2344\">version: 5.0.1<\/code><\/p>\r\n<\/li>\r\n<li data-start=\"2347\" data-end=\"2373\">\r\n<p data-start=\"2349\" data-end=\"2373\">vars: <code data-start=\"2355\" data-end=\"2371\">version: 7.1.3<\/code><\/p>\r\n<\/li>\r\n<\/ul>\r\n<p data-start=\"2375\" data-end=\"2440\">The final value used by Ansible will be <strong data-start=\"2418\" data-end=\"2427\">7.1.3<\/strong> (from vars).<\/p>\r\n<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<p>Due to my limited understanding of this, I used to define all variables in <strong>defaults<\/strong> and whenever needed to override them, I declared those variables in <strong>vars<\/strong>.<\/p>\r\n\r\n\r\n\r\n<h2 data-start=\"2447\" data-end=\"2499\"><strong data-start=\"2450\" data-end=\"2499\">But There\u2019s More: Static vs Dynamic Variables<\/strong><\/h2>\r\n<p data-start=\"2501\" data-end=\"2623\">Understanding precedence is only part of the story. Through practical usage, we also categorize variables by their nature:<\/p>\r\n<h3 data-start=\"2625\" data-end=\"2672\"><strong data-start=\"2629\" data-end=\"2670\">1. Static Variables (Constant Values)<\/strong><\/h3>\r\n<p data-start=\"2673\" data-end=\"2697\">Use <strong data-start=\"2677\" data-end=\"2690\">defaults\/<\/strong> for:<\/p>\r\n<ul data-start=\"2698\" data-end=\"2797\">\r\n<li data-start=\"2698\" data-end=\"2727\">\r\n<p data-start=\"2700\" data-end=\"2727\">Values that rarely change<\/p>\r\n<\/li>\r\n<li data-start=\"2728\" data-end=\"2751\">\r\n<p data-start=\"2730\" data-end=\"2751\">Role-wide constants<\/p>\r\n<\/li>\r\n<li data-start=\"2752\" data-end=\"2797\">\r\n<p data-start=\"2754\" data-end=\"2797\">Base URLs, paths, or fixed configurations<\/p>\r\n<\/li>\r\n<\/ul>\r\n<h3 data-start=\"2799\" data-end=\"2851\"><strong data-start=\"2803\" data-end=\"2849\">2. Dynamic Variables (Frequently Changing)<\/strong><\/h3>\r\n<p data-start=\"2852\" data-end=\"2872\">Use <strong data-start=\"2856\" data-end=\"2865\">vars\/<\/strong> for:<\/p>\r\n<ul data-start=\"2873\" data-end=\"2978\">\r\n<li data-start=\"2873\" data-end=\"2923\">\r\n<p data-start=\"2875\" data-end=\"2923\">Values likely to be customized per environment<\/p>\r\n<\/li>\r\n<li data-start=\"2924\" data-end=\"2936\">\r\n<p data-start=\"2926\" data-end=\"2936\">Versions<\/p>\r\n<\/li>\r\n<li data-start=\"2937\" data-end=\"2955\">\r\n<p data-start=\"2939\" data-end=\"2955\">Instance sizes<\/p>\r\n<\/li>\r\n<li data-start=\"2956\" data-end=\"2978\">\r\n<p data-start=\"2958\" data-end=\"2978\">User-driven inputs<\/p>\r\n<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<h3 data-start=\"2985\" data-end=\"3030\"><strong data-start=\"2988\" data-end=\"3030\">Practical Example: Tomcat Download URL<\/strong><\/h3>\r\n<p data-start=\"3032\" data-end=\"3067\">Suppose the Tomcat download URL is:<\/p>\r\n<p>\u201chttps:\/\/archive.apache.org\/dist\/tomcat\/tomcat-<strong>version<\/strong>\/\u201d<\/p>\r\n\r\n\r\n\r\n<p data-start=\"3133\" data-end=\"3145\">Breakdown:<\/p>\r\n<ul data-start=\"3146\" data-end=\"3251\">\r\n<li data-start=\"3146\" data-end=\"3218\">\r\n<p data-start=\"3148\" data-end=\"3218\"><strong data-start=\"3148\" data-end=\"3163\">Static part<\/strong> \u2192 <code data-start=\"3166\" data-end=\"3216\">\"https:\/\/archive.apache.org\/dist\/tomcat\/tomcat-\"<\/code><\/p>\r\n<\/li>\r\n<li data-start=\"3219\" data-end=\"3251\">\r\n<p data-start=\"3221\" data-end=\"3251\"><strong data-start=\"3221\" data-end=\"3237\">Dynamic part<\/strong> \u2192 <code data-start=\"3240\" data-end=\"3251\">\"version\"<\/code><\/p>\r\n<\/li>\r\n<\/ul>\r\n\r\n\r\n\r\n<p>Here, we can make a variable for the fixed value in the <strong>defaults <\/strong>with any name suppose \u201c<strong>tomcat_base_url<\/strong>\u201d and varying value should be declared in <strong>vars<\/strong>, let it be with any name suppose \u201c<strong>tomcat-version<\/strong>\u201d.<\/p>\r\n\r\n\r\n\r\n<p>So, whenever I have to use the tomcat download url in the role it will be: \u201c<strong>{{ tomcat_base_url }}\/{{ tomcat-version }}<\/strong>\u201d.<\/p>\r\n\r\n\r\n\r\n<p><strong>defaults<\/strong>: contain variables which user have to not alter.<\/p>\r\n\r\n\r\n\r\n<p><strong>vars<\/strong>: contain variables that require input by user.<\/p>\r\n\r\n\r\n\r\n<h2 data-start=\"3507\" data-end=\"3535\"><strong data-start=\"3510\" data-end=\"3535\">Best Practice Summary<\/strong><\/h2>\r\n<div class=\"_tableContainer_1rjym_1\">\r\n<div class=\"group _tableWrapper_1rjym_13 flex w-fit flex-col-reverse\" tabindex=\"-1\">\r\n<table class=\"w-fit min-w-(--thread-content-width)\" data-start=\"3537\" data-end=\"3802\">\r\n<thead data-start=\"3537\" data-end=\"3576\">\r\n<tr data-start=\"3537\" data-end=\"3576\">\r\n<th data-start=\"3537\" data-end=\"3549\" data-col-size=\"sm\">Directory<\/th>\r\n<th data-start=\"3549\" data-end=\"3559\" data-col-size=\"sm\">Purpose<\/th>\r\n<th data-start=\"3559\" data-end=\"3576\" data-col-size=\"md\">Best Use Case<\/th>\r\n<\/tr>\r\n<\/thead>\r\n<tbody data-start=\"3618\" data-end=\"3802\">\r\n<tr data-start=\"3618\" data-end=\"3714\">\r\n<td data-start=\"3618\" data-end=\"3634\" data-col-size=\"sm\"><strong data-start=\"3620\" data-end=\"3633\">defaults\/<\/strong><\/td>\r\n<td data-start=\"3634\" data-end=\"3666\" data-col-size=\"sm\">Low-priority static variables<\/td>\r\n<td data-start=\"3666\" data-end=\"3714\" data-col-size=\"md\">Constants, base URLs, default configurations<\/td>\r\n<\/tr>\r\n<tr data-start=\"3715\" data-end=\"3802\">\r\n<td data-start=\"3715\" data-end=\"3727\" data-col-size=\"sm\"><strong data-start=\"3717\" data-end=\"3726\">vars\/<\/strong><\/td>\r\n<td data-start=\"3727\" data-end=\"3761\" data-col-size=\"sm\">High-priority dynamic variables<\/td>\r\n<td data-start=\"3761\" data-end=\"3802\" data-col-size=\"md\">Versions, environment-specific inputs<\/td>\r\n<\/tr>\r\n<\/tbody>\r\n<\/table>\r\n<\/div>\r\n<\/div>\r\n<p data-start=\"3804\" data-end=\"3942\">A simple rule to follow:<\/p>\r\n<ul>\r\n<li data-start=\"3804\" data-end=\"3942\"><strong data-start=\"3834\" data-end=\"3890\">defaults = <\/strong>values users should NOT frequently change<\/li>\r\n<li data-start=\"3804\" data-end=\"3942\"><strong data-start=\"3896\" data-end=\"3940\">vars = <\/strong>values users will likely override<\/li>\r\n<\/ul>\r\n<p data-start=\"3944\" data-end=\"4044\">This structure keeps your Ansible roles maintainable, predictable, and easy for others to customize.<\/p>\r\n\r\n\r\n\r\n<h2 data-start=\"4051\" data-end=\"4068\"><strong data-start=\"4054\" data-end=\"4068\">Conclusion<\/strong><\/h2>\r\n<p data-start=\"4070\" data-end=\"4330\">Understanding when to use <strong data-start=\"4096\" data-end=\"4108\">defaults<\/strong> vs <strong data-start=\"4112\" data-end=\"4120\">vars<\/strong> 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.<\/p>\r\n<p data-start=\"4332\" data-end=\"4482\">If you feel I missed any important points or have more questions about variable precedence or Ansible best practices\u2014drop a comment. Happy Automating!<\/p>\r\n<p data-start=\"4332\" data-end=\"4482\"><strong>Source:<\/strong> <a href=\"https:\/\/docs.ansible.com\/projects\/ansible\/latest\/getting_started\/index.html\" target=\"_blank\" rel=\"noopener\">https:\/\/docs.ansible.com\/projects\/ansible\/latest\/getting_started\/index.html<\/a><\/p>\r\n<p><strong>Related Searches \u2013\u00a0<a href=\"https:\/\/opstree.com\/services\/cloud-engineering-services\/\" target=\"_blank\" rel=\"noopener\">Cloud Engineering Services<\/a> |\u00a0 <a href=\"https:\/\/opstree.com\/services\/database-and-data-engineering\/\" target=\"_blank\" rel=\"noopener\">Data Engineering Services<\/a> |\u00a0<a href=\"https:\/\/opstree.com\/services\/generative-ai-solutions\/\" target=\"_blank\" rel=\"noopener\">Generative AI Solutions<\/a><\/strong><\/p>\r\n<!-- \/wp:buttons -->","protected":false},"excerpt":{"rendered":"<p>Distinguishing between defaults and variables is an important design decision when developing an Ansible role. Defaults serve as your public interface, providing suitable values \u200b\u200bthat users can modify according to their needs. Variables, on the other hand, represent your internal framework, containing constants that must remain constant for the role to function effectively.\u00a0 Striking the &hellip; <a href=\"https:\/\/opstree.com\/blog\/2020\/03\/24\/ansible-directory-structure-default-vs-vars\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Ansible Directory Structure Explained: Defaults vs Vars (Best Practices &#038; Examples)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":159458397,"featured_media":29862,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[4011177,28070474],"tags":[768739304,1915354,697122029,1584408],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2020\/03\/Ansible-Directory-Structure-Defaults-vs-Vars-Explained.png","jetpack_likes_enabled":false,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-Fp","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/2567"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/159458397"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=2567"}],"version-history":[{"count":20,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/2567\/revisions"}],"predecessor-version":[{"id":30898,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/2567\/revisions\/30898"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29862"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=2567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=2567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=2567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}