<p>You'll notice that <a href="https://docs.ansible.com/ansible/playbooks_best_practices.html#content-organization" rel="noreferrer">the official recommendations for directory layout</a> put all of the playbooks at the root level.  This is intentional, as Ansible doesn't handle other schemes well.</p>

<p>You <em>can</em> put playbooks in a subdirectory, as you've started to do, but that will require (as you've already found) the use of relative paths from the playbooks to any other resources they use; Ansible uses the playbook path to start its search, that's just how it's written.  For the most part, that's just what you get to deal with when you make the choice to move where playbooks live.</p>

<p>However, you seem to have more nesting than you should:</p>

<pre><code>---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../../../vars/main.yaml
    - ../../../vars/vault.yaml
  ...
</code></pre>

<p>Why are you navigating up <em>three</em> directories?  I'd expect a layout that's like the official one, but with one subfolder for playbooks; then you'd end up with just</p>

<pre><code>---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../vars/main.yaml
    - ../vars/vault.yaml
  ...
</code></pre>

<p>which is a much more minor change.</p>

<hr>

<p>Secondly, it's pretty rare that you actually want to use <code>vars_files</code>.  Most variables used in Ansible either vary based on the host (and thus should go in <code>group_vars</code>/<code>host_vars</code> in the project root) or are role-specific (and thus should go in <code>vars</code>/<code>defaults</code> in the role directory).  A few documentation links:</p>

<ul>
<li><a href="https://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data" rel="noreferrer">https://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data</a></li>
<li><a href="https://docs.ansible.com/ansible/playbooks_roles.html#roles" rel="noreferrer">https://docs.ansible.com/ansible/playbooks_roles.html#roles</a></li>
<li><a href="https://docs.ansible.com/ansible/playbooks_roles.html#role-default-variables" rel="noreferrer">https://docs.ansible.com/ansible/playbooks_roles.html#role-default-variables</a></li>
</ul>

<p>Personally, I think it's best to have as little as possible in your playbooks, but delegate everything out to roles.  Here's an example entire playbook in your setup:</p>

<pre><code>- hosts: aws_instance.jenkins-agents
  roles:
    - ../roles/jenkins_agent
</code></pre>

<p>This gives you far more flexibility for re-use.</p>

<p>And if you find yourself not wanting to use relative paths for roles, you can override <a href="https://docs.ansible.com/ansible/intro_configuration.html#roles-path" rel="noreferrer"><code>roles_path</code></a> in an <code>ansible.cfg</code> in the root directory where you run your Ansible commands from.</p>

CC BY-SA 3.0
2017-06-18T20:03:30.107Z
2017-06-18T20:03:30.107Z
Xiong Chiamiov
<p>Since I can't comment on 030's answer yet (just opened an account), I'll answer here.</p>

<p>Group vars directories are relative to the Ansible path.</p>

<p>You don't have to run Ansible from /etc/ansible.  You can run it from ~/.hidden/directory/stuff if you wish.  Just make sure to keep a directory structure.  I.e.:</p>

<pre><code>/pipeline/   # ansible playbooks are here
/pipeline/roles
/pipeline/group_vars
</code></pre>

<p>Then you can run something like</p>

<pre><code>cd /pipeline
ansible-playbook deploy_app.yml
</code></pre>

<p>Which will read group vars from the pipeline/group_vars folder.  Better to cd to your ansible root folder first since it looks for paths from the current folder you're in if it can't find them in default location (/etc/ansible), such that you can put your ansible.cfg in /pipeline without having to specify other command line arguments.  You can also optionally define specific paths inside ansible.cfg as well.</p>

<p>You can take it a step further and set up separate group vars for each environment/location/etc:</p>

<pre><code>/pipeline/prod/group_vars/all.yml
/pipeline/dev/group_vars/all.yml
</code></pre>

<p>And run as follows using include-vars.</p>

<p>ansible-playbook deploy_app.yml -i prod</p>

CC BY-SA 3.0
2017-06-19T09:05:06.187Z
I would recommend sorting the variables by groups, the only thing is that if you put your inventories into a subdirectory, you should put a symlink to group_vars and hosts_vars into the inventories subdirectory.
Jiri Klouda
CC BY-SA 4.0
2017-06-18T06:30:12.443Z
2019-12-23T07:26:21.120Z
2019-12-23T07:26:21.120Z
maplebird
<p>Ansible usually takes relative path according to <code>inventory_dir</code> &amp; <code>playbook_dir</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>- debug: var=inventory_dir
- debug: var=playbook_dir
</code></pre>

CC BY-SA 4.0
2020-10-26T11:18:20.550Z
2020-10-26T11:18:20.550Z
gavenkoa
<p>To avoid such issues, that is why there are <a href="http://docs.ansible.com/ansible/intro_inventory.html#hosts-and-groups" rel="nofollow noreferrer">Hosts and Groups in Ansible</a>.</p>

<blockquote>
<pre><code>/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
</code></pre>
</blockquote>

CC BY-SA 3.0
2017-06-17T15:06:09.863Z
This doesn't answer my question, but it is interesting idea to have the values let's say per group. The variables We have are mostly related to specific groups. Just the `/etc` variant would not work for us. I hope it'll be able to pick them up from the project.
Mailo Světel
CC BY-SA 3.0
2017-06-19T08:07:32.013Z
It does not have to reside in the etc folder. If the hosts and groups vars dirs are located in ansible directory then it will work
030
CC BY-SA 3.0
2017-06-17T09:08:30.577Z
2017-06-17T09:08:30.577Z
030
<p>I had already bunch of playbooks, so I started to organize them in <em>playbooks</em> dir. It cause there must be relative paths to vars files.</p>

<p><strong>Actual playbook:</strong></p>

<pre><code>---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../../../vars/main.yaml
    - ../../../vars/vault.yaml
  ...
</code></pre>

<p>Is there any way to keep the dir structure, but avoid the lochness family (<code>../../../</code>)?</p>

<p>I know for roles You can specify path to them, but I did not find anything similar for <em>vars_files</em></p>

<p><strong>Project conditions:</strong></p>

<ol>
<li>We need to run the playbooks from the root of the project</li>
<li>Both <em>vars</em> and <em>playbooks</em> dir are in root of the project</li>
<li>This project doesn't have static inventory/hosts, but it is generated on the fly when You run some playbook</li>
</ol>

CC BY-SA 3.0
2017-06-15T14:34:00.323Z
Maybe you can use a variable for your relative part `../../../vars` ?
Tensibai
<ansible>
Playbook without relative path to vars
Mailo Světel
# Playbook without relative path to vars

(Asked by: username_0 on 2017-06-15)

I had already bunch of playbooks, so I started to organize them in playbooks dir. It cause there must be relative paths to vars files.
Actual playbook:
---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../../../vars/main.yaml
    - ../../../vars/vault.yaml
  ...

Is there any way to keep the dir structure, but avoid the lochness family (../../../)?
I know for roles You can specify path to them, but I did not find anything similar for vars_files
Project conditions:

We need to run the playbooks from the root of the project
Both vars and playbooks dir are in root of the project
This project doesn't have static inventory/hosts, but it is generated on the fly when You run some playbook

**Tags:** ansible

> **Comments:**
> **username_1**: Maybe you can use a variable for your relative part `../../../vars` ?  

---

## 4 answers

### Answer by username_2 on 2017-06-18. Score: 7

You'll notice that the official recommendations for directory layout put all of the playbooks at the root level.  This is intentional, as Ansible doesn't handle other schemes well.
You can put playbooks in a subdirectory, as you've started to do, but that will require (as you've already found) the use of relative paths from the playbooks to any other resources they use; Ansible uses the playbook path to start its search, that's just how it's written.  For the most part, that's just what you get to deal with when you make the choice to move where playbooks live.
However, you seem to have more nesting than you should:
---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../../../vars/main.yaml
    - ../../../vars/vault.yaml
  ...

Why are you navigating up three directories?  I'd expect a layout that's like the official one, but with one subfolder for playbooks; then you'd end up with just
---
- hosts:  aws_instance.jenkins-agents
  user:   ec2-user
  vars_files:
    - ../vars/main.yaml
    - ../vars/vault.yaml
  ...

which is a much more minor change.

Secondly, it's pretty rare that you actually want to use vars_files.  Most variables used in Ansible either vary based on the host (and thus should go in group_vars/host_vars in the project root) or are role-specific (and thus should go in vars/defaults in the role directory).  A few documentation links:

https://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data
https://docs.ansible.com/ansible/playbooks_roles.html#roles
https://docs.ansible.com/ansible/playbooks_roles.html#role-default-variables

Personally, I think it's best to have as little as possible in your playbooks, but delegate everything out to roles.  Here's an example entire playbook in your setup:
- hosts: aws_instance.jenkins-agents
  roles:
    - ../roles/jenkins_agent

This gives you far more flexibility for re-use.
And if you find yourself not wanting to use relative paths for roles, you can override roles_path in an ansible.cfg in the root directory where you run your Ansible commands from.


---

### Answer by username_3 on 2017-06-18. Score: 2

Since I can't comment on username_6's answer yet (just opened an account), I'll answer here.
Group vars directories are relative to the Ansible path.
You don't have to run Ansible from /etc/ansible.  You can run it from ~/.hidden/directory/stuff if you wish.  Just make sure to keep a directory structure.  I.e.:
/pipeline/   # ansible playbooks are here
/pipeline/roles
/pipeline/group_vars

Then you can run something like
cd /pipeline
ansible-playbook deploy_app.yml

Which will read group vars from the pipeline/group_vars folder.  Better to cd to your ansible root folder first since it looks for paths from the current folder you're in if it can't find them in default location (/etc/ansible), such that you can put your ansible.cfg in /pipeline without having to specify other command line arguments.  You can also optionally define specific paths inside ansible.cfg as well.
You can take it a step further and set up separate group vars for each environment/location/etc:
/pipeline/prod/group_vars/all.yml
/pipeline/dev/group_vars/all.yml

And run as follows using include-vars.
ansible-playbook deploy_app.yml -i prod

> **Comments:**
> **username_4**: I would recommend sorting the variables by groups, the only thing is that if you put your inventories into a subdirectory, you should put a symlink to group_vars and hosts_vars into the inventories subdirectory.  

---

### Answer by username_5 on 2020-10-26. Score: 1

Ansible usually takes relative path according to inventory_dir & playbook_dir:
- debug: var=inventory_dir
- debug: var=playbook_dir


---

### Answer by username_6 on 2017-06-17. Score: 1

To avoid such issues, that is why there are Hosts and Groups in Ansible.

/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball

> **Comments:**
> **username_0**: This doesn't answer my question, but it is interesting idea to have the values let's say per group. The variables We have are mostly related to specific groups. Just the `/etc` variant would not work for us. I hope it'll be able to pick them up from the project.  
> **username_6**: It does not have to reside in the etc folder. If the hosts and groups vars dirs are located in ansible directory then it will work  

---

