DEV Community

Cover image for Ansible File Structure, destructured
Azeez Lukman
Azeez Lukman

Posted on • Updated on

Ansible File Structure, destructured

The big question, Is there a recommended way to structure Ansible projects?

Well, Ansible doesn’t have enforce patterns on how you put files into folders. But there are a few common approaches popular in the ecosystem you may want to consider. This guides walks you through.

Keeping it simple πŸ˜‰

A pattern recommended though is to keep things as simple as you can, do things simply. Use advanced features only when necessary, if it begins to feel complex for the task, then it's probably complex. The documentation asks you to take the time to look for a simpler solution.

Look no further, one solution is to start with the minimum pattern that is easy to build upon when you need to, and that is what this article is all about.

A typical Ansible file-structure

Keep your files organized in your working Ansible project directory like this:

    β”œβ”€β”€ ansible.cfg
    β”œβ”€β”€ first_playbook.yml
    β”œβ”€β”€ inventory
    β”œβ”€β”€ group_vars
    β”‚Β Β  β”œβ”€β”€ vyos.yml
    β”‚Β Β  └── eos.yml
    β”œβ”€β”€ roles
    β”‚Β Β  β”œβ”€β”€ static_route
    β”‚Β Β  └── system
    β”œβ”€β”€ second_playbook.yml
    └── third_playbook.yml
Enter fullscreen mode Exit fullscreen mode

With this you can expand your inventory and create and run more network playbooks, let's destructure all these and what goes into them.


This is the ansible config file, commonly referred to as the brain and the heart of Ansible. It is file that defines Ansible config, and is responsible for how all processes in Ansible functions.

By default Ansible reads its configuration file in /etc/ansible/ansible.cfg, however this behavior can be altered. The recommended practice is either to have an ansible.cfg in your current project working directory or to set it as an environment variable.


Ansible Playbooks are way to automate deployment tasks by using a repeatable, re-usable, simple configuration management and multi-platform deployment system.

Each playbook contains one or more plays and each play defines the managed nodes to target and runs one or tasks on it. Each task calls an Ansible module. When you run a playbook, the plays are executed sequentially, play by play and each play also executes it's tasks sequentially from top to bottom.

Ansible lets you define more than one playbook with each paybook focused on one function, you can have one playbook to create your deployment and another one to destroy it. Our example structure show first_playbook.yml, second_playbook.yml and third_playbook.yml.


The Ansible inventory file defines the groups of hosts, commands, modules, and tasks a playbook can operate on. It functions as a list of managed nodes. An inventory can specify information like IP address for each managed node, you can designate different servers into groups like webservers, or databases


Ansible uses a combination of a hosts file and a group_vars directory to pull variables per host group and run Ansible plays/tasks against hosts. group_vars/all is used to set variables that will be used for every host that Ansible is ran against.

The group_vars in Ansible are a convenient way to apply variables to multiple hosts at once, they also provide a pattern for the reusability of group variables, saving you efforts to sort the hosts and also enhance the flexibility in your code.


Roles allows to easily reuse your grouped content, One way to use roles is with the roles option for a play, then ansible follow your file structure and the order listed below to execute the role and replace the play task with its values.

  • AnyΒ pre_tasksΒ defined in the play.
  • Any handlers triggered by pre_tasks.
  • Each role listed inΒ roles:, in the order listed. Any role dependencies defined in the role’sΒ meta/main.ymlΒ run first, subject to tag filtering and conditionals.
  • AnyΒ tasksΒ defined in the play.
  • Any handlers triggered by the roles or tasks.
  • AnyΒ post_tasksΒ defined in the play.
  • Any handlers triggered by post_tasks.

Time for an example

In addition to the above recommendations, i also recommend that you practalize your knowledge, Rafael has written an amazing article on how to automate the setup of a Kubernetes cluster on GCP following a similar structure.

This is the format he implemented

└── ansible                    # Ansible top-level folder
    β”œβ”€β”€ ansible.cfg            # Ansible config file
    β”œβ”€β”€ create-k8s.yml         # Ansible playbook to provision env
    β”œβ”€β”€ destroy-k8s.yml        # Ansible playbook to destroy env
    β”œβ”€β”€ inventory             
    β”‚   └── gcp.yml            # Ansible inventory file
    └── roles
        β”œβ”€β”€ destroy_k8s        # Ansible role to remove k8s cluster        
        β”‚   └── tasks
        β”‚       └── main.yml
        β”œβ”€β”€ destroy_network    # Ansible role to remove VPC
        β”‚   └── tasks
        β”‚       └── main.yml
        β”œβ”€β”€ k8s                # Ansible role to create k8s cluster
        β”‚   └── tasks
        β”‚       └── main.yml
        └── network            # Ansible role to create VPC
            └── tasks
                └── main.yml
Enter fullscreen mode Exit fullscreen mode


Ansible makes deploying your infrastructure easier and it's best when used as intended, Don't over complicate it, start simple and with time you would discover what structure works best for your organization.

Thank you for reading, I hope you learned a lot already. I'm Azeez Lukman and here's a developer's journey building something awesome every day. Please let's meet on Twitter, LinkedIn, GitHub and anywhere else @robogeeek95

Top comments (0)