Introduction
When you start with Ansible, putting everything in one big playbook.yml file is fine. But as your automation grows to hundreds of lines, that file becomes a mess.
The solution is Ansible roles.
Roles are like folders in a file cabinet. Instead of one giant document, you separate things into logical folders: one folder for "Web Server" tasks, one for "Database" tasks, etc.
Roles matter because automation eventually becomes software engineering. Once playbooks grow beyond a few tasks, structure, naming, and reuse become as important as simply making the first run succeed.
In this lab, you will:
- Create a standardized Role structure using
ansible-galaxy. - Move tasks into that Role.
- Run the Role from a simple "Master Playbook".
Roles matter because scalable automation needs structure. As codebases grow, organization becomes just as important as getting the first successful run.
Initialize a Role
First, let's create the folder structure. You could make all the folders manually, but Ansible includes a tool called ansible-galaxy that does it for you.
This standard layout is valuable because it gives every role predictable places for tasks, variables, files, templates, and handlers. Teams can read each other's automation more easily when that structure stays consistent.
Go to your project directory:
cd ~/project
Create a directory to hold your roles:
mkdir roles
Now, create a new role named myrole. Think of this as creating a "package" or "module" for your automation.
ansible-galaxy init roles/myrole
Let's look at what it created:
ls -R roles/myrole
You will see many folders (tasks, handlers, vars, etc.).
- tasks: Where the actual steps (install, start, copy) go.
- vars: Where variables go.
- files: Where static files (like images) go.
We will focus on the tasks folder today.
Define Role Tasks
Now we need to put some work into our role. The main list of tasks for a role lives in tasks/main.yml.
We will create a simple task that installs the tree command (a useful utility for viewing directory structures).
Open the role's task file:
nano roles/myrole/tasks/main.yml
Add the following content. Notice we do not start with tasks: here, because we are already inside the tasks file!
---
## tasks file for roles/myrole
- name: Ensure tree is installed
apt:
name: tree
state: present
become: yes
Key Difference: In a normal playbook, you have a tasks: section. Inside a role, the file is the list of tasks, so you just start listing them directly.
That separation is one reason roles improve reuse. The role owns a focused slice of automation logic, while the playbook decides when and where to include it.
Save and exit.
Create Master Playbook
Now you have a Role, but a Role doesn't run by itself. You need a "Master Playbook" to call it.
Create a file named site.yml in your main project folder:
nano ~/project/site.yml
This playbook will be very short. It just says "On these hosts, run this role."
At this point the playbook becomes more of an orchestrator than a container for all details. That is the architectural shift roles are meant to create.
---
- hosts: localhost
connection: local
roles:
- myrole
Understanding the code:
roles:: Instead of atasks:list, we provide a list of roles.- myrole: Ansible looks for a folder namedmyroleinside theroles/directory and executes whatever is intasks/main.yml.
Save and exit.
Validate and Run
Before we run it, let's make sure we didn't make any typing mistakes. Ansible has a built-in syntax checker.
Run this command:
ansible-playbook -i inventory --syntax-check site.yml
If everything is good, it will just print playbook: site.yml.
If there are errors, read the message carefully—it usually points to the exact line number where the indentation is wrong.
Now, run the playbook for real:
ansible-playbook -i inventory site.yml
You should see it execute the task from your role: TASK [myrole : Ensure tree is installed] ... changed
Summary
In this lab, you learned the "Professional" way to structure Ansible.
- Initialized a Role: Using
ansible-galaxyto create the standard folder structure. - Defined Tasks: Placed your logic inside
tasks/main.yml. - Used the Role: Called the role from a clean, simple
site.ymlmaster playbook.
As you write more automation, you will create roles for everything (e.g., apache, mysql, common), making your code reusable and easy to read.


