RousselTMLEARNING

Article · Ansible: from discovery to expertise

Structuring your code with roles

1. Why roles? #

Reuse, test and share.

From a monolithic playbook to a role #

A growing playbook becomes unreadable. A role groups everything related to a component (installation, configuration, service) in a standardized structure: it can be reused across projects, tested independently and shared through Ansible Galaxy.

Directory layout of an Ansible role
Only tasks/main.yml is mandatory.

Creating the directory layout #

mkdir -p roles && cd roles
ansible-galaxy role init nginx
tree nginx
nginx/
├── README.md
├── defaults/main.yml     # variables par défaut (priorité la plus basse)
├── files/                # fichiers copiés tels quels
├── handlers/main.yml     # actions déclenchées par notify
├── meta/main.yml         # métadonnées et dépendances
├── tasks/main.yml        # point d'entrée du rôle
├── templates/            # fichiers Jinja2 (.j2)
├── tests/                # inventaire et playbook de test
└── vars/main.yml         # variables internes (priorité élevée)

2. Writing a complete role: nginx #

Tasks, defaults, templates and handlers.

defaults and tasks #

# roles/nginx/defaults/main.yml
nginx_port: 80
nginx_server_name: "{{ ansible_fqdn }}"
nginx_worker_processes: auto
nginx_enable_service: true
# roles/nginx/tasks/main.yml
- name: Installer nginx
  ansible.builtin.package:
    name: nginx
    state: present

- name: Déployer la configuration du site
  ansible.builtin.template:
    src: site.conf.j2
    dest: /etc/nginx/conf.d/site.conf
    owner: root
    mode: "0644"
    validate: nginx -t -c /etc/nginx/nginx.conf
  notify: Recharger nginx

- name: Démarrer et activer nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: "{{ nginx_enable_service }}" 

Template and handler #

# roles/nginx/templates/site.conf.j2
server {
    listen {{ nginx_port }};
    server_name {{ nginx_server_name }};
    root /var/www/{{ nginx_server_name }};
    access_log /var/log/nginx/{{ nginx_server_name }}.access.log;
}
# roles/nginx/handlers/main.yml
- name: Recharger nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded
Good to know: A handler runs only once, at the end of the play, and only if a task that notifies it actually changed something. Force it to run immediately with - meta: flush_handlers.

3. Using a role #

In a playbook, with its variables.

Calling the role #

# site.yml
- hosts: webservers
  become: true
  roles:
    - role: nginx
      vars:
        nginx_port: 8080
    - role: monitoring_agent
      tags: [monitoring]
ansible-playbook -i inventories/lab/hosts.ini site.yml
ansible-playbook site.yml --tags monitoring
ansible-playbook site.yml --list-tasks

You can also call it dynamically in the middle of a task list with include_role (conditional or looped execution) or import_role (static inclusion):

tasks:
  - name: Installer le serveur web
    ansible.builtin.include_role:
      name: nginx
    when: ansible_os_family == "Debian" 

Dependencies between roles #

# roles/wordpress/meta/main.yml
dependencies:
  - role: nginx
    vars: { nginx_port: 80 }
  - role: mariadb

4. Sharing with Ansible Galaxy and collections #

Don't reinvent the wheel.

Installing roles and collections #

ansible-galaxy role search nginx --author geerlingguy
ansible-galaxy role install geerlingguy.docker
ansible-galaxy collection install community.general ansible.posix

# Versionner les dépendances du projet
cat requirements.yml
roles:
  - name: geerlingguy.docker
    version: 7.4.1
collections:
  - name: community.general
    version: ">=9.0.0"

ansible-galaxy install -r requirements.yml

Best practices #

  • One role = one responsibility; name it after the component (nginx, postgres).
  • Prefix all variables with the role name (nginx_port) to avoid collisions.
  • Put modifiable values in defaults/ and reserve vars/ for internal constants.
  • Make every task idempotent and test it with Molecule (see « Going further »).
Common mistake: Avoid writing a monster role that installs, configures and monitors ten components: it becomes impossible to test and reuse.

📄 Ansible: structuring your code with roles →

My progress

  • ⏱ Estimated time : ≈ 14 min

Sign in to track your progress and take notes. Sign in

💬 Questions about this lesson

No questions yet: be the first to ask for help or share your configuration.

Ask a question about this lesson →

Course Glossary

Ansible

An open source IT automation tool (IaC) enabling configuration management, application deployment, and orchestration, operating agentlessly via SSH.

Recommended Articles

Ansible: managing your infrastructure with playbooks (Infrastructure as Code)

Write production playbooks: project structure, plays, handlers, tags, serial strategy, error hand...

Ansible best practices: structure, idempotence, security and quality

Ansible best practices: project organization, naming, FQCN, idempotence, modules rather than shel...

Ansible: generating dynamic files with Jinja2 and facts

Create dynamic configuration files: Jinja2 templates, variables, facts, filters, loops, condition...

Ansible: going further (testing, quality, CI/CD and performance)

Industrialize Ansible: ansible-lint, yamllint, Molecule, continuous integration, collections, exe...

Automation and infrastructure as code for Elasticsearch: API, Terraform, Ansible and CI/CD

Automate Elasticsearch administration: REST API and clients, the elasticstack Terraform provider ...

Ansible: driving your automations with a graphical interface (AWX, Semaphore, AAP)

Compare and install Ansible's graphical interfaces: AWX, Ansible Automation Platform, Semaphore a...

Ansible: the inventory (static, dynamic, groups and variables)

Understand and master the Ansible inventory: INI and YAML files, groups, host and group variables...

Ansible: managing security (Vault, SSH, privileges and secrets)

Securing Ansible: Ansible Vault, SSH key authentication, become and sudo, no_log, hardening the c...

Ansible: ad-hoc commands

Run immediate actions on a fleet of servers with ansible: the ping, command, shell, copy, apt, se...

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!