A medida que los proyectos de automatización crecen, mantener todo en un solo playbook se vuelve insostenible. Los roles de Ansible resuelven este problema proporcionando una estructura modular, reutilizable y autónoma para cada componente de la infraestructura. Combinados con templates Jinja2, permiten gestionar configuraciones dinámicas de forma elegante.

Estructura de un rol de Ansible

Un rol sigue una convención de directorios predefinida. Cada subdirectorio tiene un propósito específico y Ansible cargará automáticamente su contenido en el orden correcto. Los directorios principales son: tasks, handlers, templates, vars, defaults y meta.

«`
# Crear la estructura base del rol
ansible-galaxy init roles/nginx

# Estructura generada:
# roles/nginx/
# ├── defaults/
# │   └── main.yml        # Variables por defecto (baja prioridad)
# ├── handlers/
# │   └── main.yml        # Handlers del rol
# ├── meta/
# │   └── main.yml        # Metadatos y dependencias
# ├── tasks/
# │   └── main.yml        # Tareas principales (punto de entrada)
# ├── templates/
# │   └── ...             # Plantillas Jinja2
# ├── tests/
# │   ├── inventory
# │   └── test.yml
# └── vars/
#     └── main.yml        # Variables internas (alta prioridad)```


Uso de templates Jinja2 en Ansible

Los templates Jinja2 permiten generar archivos de configuración dinámicos combinando variables, condicionales y bucles. Se colocan en el directorio templates/ del rol con extensión .j2 y se despliegan con el módulo template.

```
{# roles/nginx/templates/nginx.conf.j2 #}
{# Configuración generada por Ansible - {{ ansible_managed }} #}

user www-data;
worker_processes {{ nginx_worker_processes | default('auto') }};
error_log /var/log/nginx/error.log {{ nginx_error_level | default('warn') }};
pid /run/nginx.pid;

events {
    worker_connections {{ nginx_worker_connections | default(1024) }};
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;

    {% if nginx_gzip_enabled %}
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    {% endif %}

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}```


El módulo template procesa la plantilla y copia el resultado al nodo destino, reemplazando las variables con sus valores reales:

```
# tasks/main.yml del rol nginx
- name: Desplegar configuración principal de Nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
  notify: Recargar Nginx

- name: Desplegar configuración del sitio virtual
  template:
    src: site.conf.j2
    dest: "/etc/nginx/sites-available/{{ server_name }}"
  notify: Recargar Nginx```


Dependencias entre roles

Los roles pueden declarar dependencias de otros roles mediante el archivo meta/main.yml. Esto permite construir una jerarquía de roles donde, por ejemplo, un rol wordpress dependa de los roles nginx, php-fpm y mariadb. Ansible ejecutará automáticamente las dependencias antes del rol que las declara.

```
# roles/wordpress/meta/main.yml
---
dependencies:
  - role: nginx
    vars:
      nginx_port: 8080
  - role: php-fpm
    vars:
      php_version: "8.4"
  - role: mariadb
    vars:
      mariadb_version: "10.11"
      mariadb_databases:
        - name: wordpress```


Ejemplo completo: rol nginx reutilizable

Un rol completo para Nginx incluye defaults sensatos, tasks idempotentes, handlers, templates y dependencias. Esta estructura permite reutilizar el mismo rol en múltiples proyectos con diferentes configuraciones simplemente ajustando las variables.

```
# defaults/main.yml — valores por defecto
---
nginx_port: 80
nginx_worker_processes: "auto"
nginx_worker_connections: 1024
nginx_gzip_enabled: true
nginx_error_level: warn
server_name: "localhost"
document_root: "/var/www/html"

# handlers/main.yml
---
- name: Recargar Nginx
  service:
    name: nginx
    state: reloaded

- name: Verificar configuración Nginx
  command: nginx -t```


Con los roles y templates ya dominas la organización profesional de proyectos Ansible. En el siguiente artículo pondremos esto en práctica desplegando un stack completo de servidor web con Nginx, PHP-FPM y MariaDB.