Let’s talk about Ansible structure.
How I use Ansible is by creating tasks and playbooks so that, ideally, I don’t need to access the server’s shell directly for configuration.
I played around a lot, and honestly, I had no structure in the beginning. I wasn’t too concerned about deployment processes or potential side effects initially. My aim was to use Ansible to automate many configuration and deployment tasks, streamlining steps often handled in separate CI/CD tool scripts.
Now, onto project structure, which in my opinion is very important, primarily for automation. The goal is first to get comfortable with the tool, then to get results for what you actually want to achieve. This should ideally happen quickly. After you achieve some results, you’ll start to identify your key needs. For example, my key parts were:
Main setup: The non-negotiable base configuration (OS settings, firewalls, common packages) for all your servers. Feature setups: Optional services needed for specific functions, like installing Redis, setting up Docker, or adding a specific firewall rule to open a port. Main services: The core applications that are repeatedly updated and maintained, like a web application. These different types of tasks can be grouped. Ansible’s tag system and roles are useful for this.
Repeating tasks helps build a routine. You’ll then identify exactly which parts you do repeatedly – these are candidates for automation. At this point, you can extract these parts and start building a more defined structure.
In my journey, I always start simple, often with fewer directories.
For example, when using a flatter hierarchy initially, my naming convention for task files might just be simple and descriptive, perhaps including the service name like nginx_tasks.yml or redis_tasks.yml.
If the number of files grows and I find myself needing to check the structure multiple times to get an overview, I would evolve it towards using standard Ansible roles, organized perhaps by service or function, which looks more like this:
├── roles/ │ ├── common/ │ │ └── tasks/ │ │ └── main.yml │ ├── redis/ │ │ └── tasks/ │ │ └── main.yml │ └── webapp/ │ └── tasks/ │ └── main.yml ├── playbook.yml └── inventory/
In development I can warmly recommend the mindset to start simple even with the directory part. In my mind an underscore represents a subdirectory. This is how the naming convention should be in my opinion.