Ansible project directories structure

by (September 22, 2016)

Posted in Provision  Tags:Ansible

After several years of automation with Ansible we come to this directory structure:

├── clusters
│   ├── prod
│   ├── sandboxes
│   ├── staging
├── files
├── library
├── roles
│   ├── roleA
│   ├── roleB
│   ├── roleC
├── tasks
├── templates
└── vars


You have one project, but very often you have several environments or clusters, as usual it will be at least production and staging, often sandboxes.

One Ansible Project, many clusters

And here comes the magic - in Ansible’s variables definition (hosts_vars, groups_vars) stored relative to the inventory file. This way all configuration related to specific cluster goes to directories under cluster/yourcluster i.e.:

│   ├── prod
│   │   ├── files
│   │   ├── group_vars
│   │   └── templates

To files you put static files specific only for this cluster. Like public keys of users with access only to this cluster (but as for pub keys it is better to place them to global files and just specify user names in cluster’s definition). To templates you put… surprise: templates, but again only cluster specific templates, working example - AWS CloudFormation templates. And the one, the main, the great: group_vars - all variables go to this directory. So when you need to play some playbook against specific cluster, just use:

ansible-playbook -i clusters/prod/hosts some-playbook.yml


Global static files placed in this directory and again good example - ssh pub keys, you can use them across all clusters.


These days unfortunately can be a situation when some Ansible module just don’t have some feature you need or even there is just no module exist, so yo have to hack or write modules yourself, it happens all the time.


The biggest directory in your project, here comes all the logic and lots of magic.


In project you will have some playbooks, for example playbook for rolling-update the project running on your cluster. To not have a big fat playbook, structurize it and use files in tasks/ as functions, call them with include, working example:

$ cat tasks/slack.yml
- name: Send notification to Slack
    token={{ slack.token }}
    channel={{ }}
    username={{ slack.username }}
    msg={{ slack_message }}
    color={{ slack_color|default('normal') }}
  when: slack.enabled and slack_message is defined
  ignore_errors: yes

$ cat deploy.yml
- hosts: backends
  - include: tasks/slack.yml
      slack_message="Updating cluster"
    run_once: True
  - include: tasks/deploy.yml


Some templates not specific to roles and common for all clusters, working example - template of configuration file for dynamic inventory script.


Some global variables can be placed here, for example AWS keys.

Let us know!

Contact details:


Services you are interested in: