# New "Best Practices" documentation, please help me review

**URL:** <https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384>\
**Category:** Ansible Project\
**Created:** [February 19, 2013, 4:39am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384 "2013-02-19T04:39:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 19, 2013, 4:39am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/1 "2013-02-19T04:39:57Z")

</div>

I've had a lot of requests for a better understanding of how to  
organize playbook content, so I've written a lot more about how I do  
it. Obviously everyone is going to have their own approach, so our  
best practice here is mostly a suggestion, but it's not far off from  
what a lot of people do. But in the end, it's just one way to do it.  
Some review on this would be welcome before we push it to the doc  
site:

[https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst](https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst)

A few key things I am trying to show.

\* playbooks are mappings between groups and roles  
\* a particular style of organization allows more power in selectively  
running things if so organized, I like to have playbooks for each  
"class" of system and think of playbooks as mapping groups to roles.  
\* files/templates/handlers/tasks as subdirectories allows for  
organization of content a little bit. Subdirectories based on role.  
\* where to put variable defaults (a very common request) and to show  
an example of group\_vars/host\_vars  
\* how to keep staging and production seperate and to prevent surprises

I'm going to be doing an example repo of what this looks like on  
github here, but I also wanted to be able to explain it on the docs  
page as well.

I freehanded all of the YAML without checking it (don't try this at  
home!), so there may be some errors -- patches to the RST files are  
fair game!

--Michael

---

<div class="post-metadata">

**Author:** ![Arne\_Jacobs](https://avatars.discourse-cdn.com/v4/letter/a/9f8e36/32.png) [@Arne\_Jacobs](https://forum.ansible.com/u/Arne_Jacobs)\
**Post date:** [February 19, 2013, 10:43am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/2 "2013-02-19T10:43:21Z")

</div>

Nice to read, thank you!

One question regarding tags: I couldn’t find anything in the documentation regarding the “tags=…” argument on includes. What is the semantics of that? Does it limit the included tasks to those with the given tag (which would make the example seem a bit odd) or does it add the given tag to the included tasks?

Cheers,

elektrokokke

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 19, 2013, 1:16pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/3 "2013-02-19T13:16:19Z")

</div>

It does the latter, it applies tags to what is included so they can be  
filtered by tag with "--tags" if you want.

---

<div class="post-metadata">

**Author:** ![Seth\_Vidal](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@Seth\_Vidal](https://forum.ansible.com/u/Seth_Vidal)\
**Post date:** [February 19, 2013, 4:22pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/4 "2013-02-19T16:22:47Z")

</div>

Michael,  
&nbsp;&nbsp;in looking at the layout you describe - I worry how well that layout scales for middle-largish deployments.

In places with 200ish hosts - if you have 50 different variations of server that top level directory is going to be difficult to traverse and find everything in.

Maybe a playbooks subdir?

Additionally, in the fedora ansible repo I setup I had added subdirs of 'groups' and 'hosts' for playbooks so I could tell when a specific system had its own, specific playbook vs being a member of a group.

Would either of those items make sense for adding to the best practices?

-sv

---

<div class="post-metadata">

**Author:** ![mujahideen.solutions](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@mujahideen.solutions](https://forum.ansible.com/u/mujahideen.solutions)\
**Post date:** [February 19, 2013, 4:24pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/5 "2013-02-19T16:24:47Z")

</div>

I tend to organize my playbooks as:  
/etc/ansible/playbooks/desktops/archlinux/playbook\_here.yml  
/etc/ansible/playbooks/servers/debian/playbook\_here.yml  
etc…

---

<div class="post-metadata">

**Author:** ![Yves\_Dorfsman](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@Yves\_Dorfsman](https://forum.ansible.com/u/Yves_Dorfsman)\
**Post date:** [February 19, 2013, 4:35pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/6 "2013-02-19T16:35:27Z")

</div>

I don't use tags as part of my normal workflow yet, but I use them a lot to debug specific tasks. Rather create another playbook with just that task, or run the entire playbook, I add a tag to the task(s) I am trying to debug:

[https://coderwall.com/p/ur8qnw?i=1&p=2&q=sort%3Ascore+desc&t[]=ansible](https://coderwall.com/p/ur8qnw?i=1&p=2&q=sort%3Ascore+desc&t%5B%5D=ansible)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 19, 2013, 4:58pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/7 "2013-02-19T16:58:32Z")

</div>

> Michael,  
> in looking at the layout you describe - I worry how well that layout scales  
> for middle-largish deployments.
> 
> In places with 200ish hosts - if you have 50 different variations of server  
> that top level directory is going to be difficult to traverse and find  
> everything in.

Yeah, probably. I think about places with 200 hosts all the time (we  
have quite a few people running much much larger), but they are  
generally \*mostly\* homogenous.

> Maybe a playbooks subdir?
> 
> Additionally, in the fedora ansible repo I setup I had added subdirs of  
> 'groups' and 'hosts' for playbooks so I could tell when a specific system  
> had its own, specific playbook vs being a member of a group.

Not sure I would see host specifics playbooks being recommended, per  
se, but it's a possible thing people could do if they wanted.

If a host is the only one in the role, I'd still like to see it  
modelled based on the group.

But obviously every site is totally different.

---

<div class="post-metadata">

**Author:** ![Yves\_Dorfsman](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@Yves\_Dorfsman](https://forum.ansible.com/u/Yves_Dorfsman)\
**Post date:** [February 19, 2013, 5:07pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/8 "2013-02-19T17:07:40Z")

</div>

I agree. I have a directory structure very similar to the Michael's best practice but with a few differences:

-I don't have any playbook at the top level. It does have the disadvantage that all references have to point to ../.

-I find webtier, monitoring too simplistic. Typically an "apps" is a combination of a web server, a database server etc.... Yet, install tomcat or nginx is always the same thing, it's their customisations that makes a big difference, so I have a basic install playbook, then each apps has its own customisation of which makes an include of the basic install. So I have something along these lines:

&nbsp;&nbsp;&nbsp;&nbsp;install-software/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;install-tomcat.paybook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;install-nginx.playbook.yaml

&nbsp;&nbsp;&nbsp;&nbsp;tasks/

&nbsp;&nbsp;&nbsp;&nbsp;accounting/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;templates/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-all.playbook  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-tomcat.playbook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-ngix.playbook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-oracle.playbook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tasks/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-tomcat.tasks.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accounting-oracle.tasks.yaml

&nbsp;&nbsp;&nbsp;&nbsp;logistics/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logisctics-all.playbook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logistics-nginx.playbook.yaml  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logistics-nginx.tasks.yaml

In this example:  
logisctics-all.playbook.yaml makes an include of logistics-nginx.playbook.yaml and logistics-nginx.tasks.yaml

logistics-nginx.playbook.yaml makes an include of logistics-nginx.tasks.yaml and ../install-software/install-nginx.playbook.yaml

etc...

-depending on the size of a project or apps, I'll create subriectories for tasks, vars, etc... specific to that apps, or I'll just keep them all in one dir (if there are only a handful of files). Because I mix files into the same directory, I do add .paylbook., .tasks., .vars., to all my files.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 19, 2013, 5:17pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/9 "2013-02-19T17:17:17Z")

</div>

Yeah, it was kind of a starting point. If I make a very detailed  
structure, it's hard on the simpler environments.

If I go too simple, it's hard to grok for the more complex environments.

I'm thinking maybe we explain it somewhat like I have it now, and then  
maybe have an "alternate structure suggestions" or something after...

---

<div class="post-metadata">

**Author:** ![kahlil.hodgson](https://avatars.discourse-cdn.com/v4/letter/k/b9bd4f/32.png) [@kahlil.hodgson](https://forum.ansible.com/u/kahlil.hodgson)\
**Post date:** [February 19, 2013, 8:57pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/10 "2013-02-19T20:57:32Z")

</div>

Using multiple inventory files is an interesting idea -- making the concept of, say, 'hosts: all' dynamic. Much simpler than managing corresponding top level groups or multiple target specific playbooks.

K

---

<div class="post-metadata">

**Author:** ![Kavin](https://avatars.discourse-cdn.com/v4/letter/k/ba8739/32.png) [@Kavin](https://forum.ansible.com/u/Kavin)\
**Post date:** [February 20, 2013, 3:02am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/11 "2013-02-20T03:02:25Z")

</div>

This is great, my 2c.

Is there sample best practice on how to write playbooks for multiple OS, like for Centos5/6 and Ubuntu, Like deciding to use yum or apt [etc.as](http://etc.as) of now, i am using global\_var.yml and deciding if its ubuntu or centos and which flavor and run certain actions based on that.

Also Would be nice for Best Practice’s to be for large deployments or have separate for small(easy) and large(more complex). So people learning to use Ansible know how to setup so it can scale easily. I personally would be very interested in a complex playbook best practices , with documentation on what each playbook does and how it works. (Every one learns differently 🙂 i learn by examples), Let me know if this is reasonable.

Regards,–  
Kavin Kankeshwar

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 20, 2013, 4:18am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/12 "2013-02-20T04:18:11Z")

</div>

> This is great, my 2c.
> 
> Is there sample best practice on how to write playbooks for multiple OS,  
> like for Centos5/6 and Ubuntu, Like deciding to use yum or apt etc.as of  
> now, i am using global\_var.yml and deciding if its ubuntu or centos and  
> which flavor and run certain actions based on that.

There is the $ansible\_pkg\_mgr fact but because so many other details  
are different I really think (in any tool)  
seperating those is appropriate in many cases.

> Also Would be nice for Best Practice's to be for large deployments or have  
> separate for small(easy) and large(more complex). So people learning to use  
> Ansible know how to setup so it can scale easily. I personally would be very  
> interested in a complex playbook best practices , with documentation on what  
> each playbook does and how it works. (Every one learns differently 🙂 i  
> learn by examples), Let me know if this is reasonable.

I think what I decided to show was 80% complex-ish, and at that point,  
individual needs may make things vary quickly.

Though I would like more people to show github examples of what they  
are doing and maybe we can link to several in that section to show  
other approaches?

---

<div class="post-metadata">

**Author:** ![Kavin](https://avatars.discourse-cdn.com/v4/letter/k/ba8739/32.png) [@Kavin](https://forum.ansible.com/u/Kavin)\
**Post date:** [February 20, 2013, 4:24am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/13 "2013-02-20T04:24:12Z")

</div>

> > This is great, my 2c.
> > 
> > Is there sample best practice on how to write playbooks for multiple OS,  
> > like for Centos5/6 and Ubuntu, Like deciding to use yum or apt [etc.as](http://etc.as) of  
> > now, i am using global\_var.yml and deciding if its ubuntu or centos and  
> > which flavor and run certain actions based on that.
> 
> There is the $ansible\_pkg\_mgr fact but because so many other details  
> are different I really think (in any tool)  
> seperating those is appropriate in many cases.
> 
> > Also Would be nice for Best Practice’s to be for large deployments or have  
> > separate for small(easy) and large(more complex). So people learning to use  
> > Ansible know how to setup so it can scale easily. I personally would be very  
> > interested in a complex playbook best practices , with documentation on what  
> > each playbook does and how it works. (Every one learns differently 🙂 i  
> > learn by examples), Let me know if this is reasonable.
> 
> I think what I decided to show was 80% complex-ish, and at that point,  
> individual needs may make things vary quickly.
> 
> Though I would like more people to show github examples of what they  
> are doing and maybe we can link to several in that section to show  
> other approaches?

I would love it, To see a bunch or repos and see how its done And will share our repo too, but its too Amateurish now, Once i refactor to use best practices and see some examples will share it.

---

<div class="post-metadata">

**Author:** ![Mark\_Maas](https://avatars.discourse-cdn.com/v4/letter/m/7c8e57/32.png) [@Mark\_Maas](https://forum.ansible.com/u/Mark_Maas)\
**Post date:** [February 20, 2013, 1:05pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/14 "2013-02-20T13:05:39Z")

</div>

The “group\_by” example: [https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst#operating-system-and-distribution-variance](https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst#operating-system-and-distribution-variance)

Needs to get some additional information. Namely; that even though the name “CentOS” is created by group\_by, the variables in a “host\_vars/CentOS” file will only be loaded when there is a [CentOS] section with the server name in the inventory file.

plus:

```auto
- hosts: all
  tasks:
     - group_by key=${ansible_distribution}

```

Needs to be:

```auto
- hosts: all
  tasks:
     - group_by: key=${ansible_distribution}

```

forgot the colon in the “free hand” 😉

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 20, 2013, 1:22pm UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/15 "2013-02-20T13:22:49Z")

</div>

> The "group\_by" example:  
> [https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst#operating-system-and-distribution-variance](https://github.com/ansible/ansible/blob/devel/docsite/rst/bestpractices.rst#operating-system-and-distribution-variance)
> 
> Needs to get some additional information. Namely; that even though the name  
> "CentOS" is created by group\_by, the variables in a "host\_vars/CentOS" file  
> will only be loaded when there is a [CentOS] section with the server name in  
> the inventory file.

Thanks, didn't think of that -- we may want to streamline that at some point.

> plus:
> 
> - hosts: all  
> &nbsp;&nbsp;tasks:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- group\_by key=${ansible\_distribution}
> 
> Needs to be:
> 
> - hosts: all  
> &nbsp;&nbsp;tasks:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- group\_by: key=${ansible\_distribution}
> 
> forgot the colon in the "free hand" 😉

Nice, I also noticed I typoed "ntp" vs "ntpd" in a few places.

---

<div class="post-metadata">

**Author:** ![Mark\_Maas](https://avatars.discourse-cdn.com/v4/letter/m/7c8e57/32.png) [@Mark\_Maas](https://forum.ansible.com/u/Mark_Maas)\
**Post date:** [February 21, 2013, 5:48am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/16 "2013-02-21T05:48:22Z")

</div>

I’d say, The whole concept makes less sense to use with this. 🙂

---

<div class="post-metadata">

**Author:** ![Lorin\_Hochstein1](https://avatars.discourse-cdn.com/v4/letter/l/ce73a5/32.png) [@Lorin\_Hochstein1](https://forum.ansible.com/u/Lorin_Hochstein1)\
**Post date:** [February 22, 2013, 4:00am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/17 "2013-02-22T04:00:13Z")

</div>

Maybe out of scope for this particular document, but I think it would be useful to capture different scenarios. Probably easiest to crowd-source it, different people could document how they structure things for their organizations (not so different from the content in this thread). This way, a reader could say, “Ah, scenario X matches my context the closest, I’ll do mine in a similar way”.

I’m not quite sure where to put this type of content.

Lorin

---

<div class="post-metadata">

**Author:** ![Lorin\_Hochstein1](https://avatars.discourse-cdn.com/v4/letter/l/ce73a5/32.png) [@Lorin\_Hochstein1](https://forum.ansible.com/u/Lorin_Hochstein1)\
**Post date:** [February 22, 2013, 4:03am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/18 "2013-02-22T04:03:40Z")

</div>

It is great to be able to change inventory files. A problem we run into is that we use different ssh keys for staging and production. Is it possible to specify an ssh key as a variable in an inventory file so we can use different keys like that?

Lorin

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 22, 2013, 5:18am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/19 "2013-02-22T05:18:14Z")

</div>

Not presently, normally you have to use ssh-agent anyway.

---

<div class="post-metadata">

**Author:** ![Lorin\_Hochstein1](https://avatars.discourse-cdn.com/v4/letter/l/ce73a5/32.png) [@Lorin\_Hochstein1](https://forum.ansible.com/u/Lorin_Hochstein1)\
**Post date:** [February 24, 2013, 2:08am UTC](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384/20 "2013-02-24T02:08:07Z")

</div>

Yeah, ssh-agent is the right way to go.

What I probably should do is write a local\_action task that calls “ssh-add -l” and checks if the required keys are present, and if not, bails out. That way, it’s clear to the user that the failure was because keys hadn’t been loaded yet. Something like:

- name: ensure keys are present in local ssh-agent  
local\_action: shell ssh-add -l | grep --silent $item  
with\_items: ssh\_key\_fingerprints

Take care,

Lorin

[Next page](https://forum.ansible.com/t/new-best-practices-documentation-please-help-me-review/12384.md?page=2)
