From Monolithic Playbooks to Reusable Components
A playbook that configures an entire application stack — OS hardening, package installation, service configuration, log rotation, monitoring agent setup — can easily grow to hundreds of tasks across thousands of lines. This becomes unmaintainable and impossible to share across projects.
Roles are Ansible's answer to this problem. A role is a standardized directory structure that packages tasks, variables, templates, files, and handlers into a self-contained, reusable unit. You can think of a playbook as the conductor and roles as the musicians — the playbook orchestrates which roles run on which hosts, while each role handles its own domain completely.
Standard Role Directory Structure
A generated role skeleton has a fixed, standardized shape: tasks (the entry point — the list of things this role does), handlers, templates, static files, role-internal variables, low-precedence defaults meant to be overridden, and metadata describing the role's author and its dependencies on other roles. Ansible automatically loads files from these directories when the role is invoked — you don't need to explicitly include them.
Using Roles in a Playbook
A playbook applies roles to a group of hosts as an ordered list — OS hardening first, then nginx configuration, then an application-deploy role passed a specific version to install — with the playbook itself staying short since each role owns its own domain completely.
Ansible Galaxy
Ansible Galaxy is the community hub for sharing roles. Rather than writing a role to install and configure PostgreSQL from scratch, you can install and pin a battle-tested community role by name and version in a requirements file, the same reproducibility discipline as a lockfile in any other ecosystem. Always pin role versions. Unpinned roles can introduce breaking changes when the upstream author updates them.