Subsections of Roles

Ansible Galaxy Roles

Using Ansible Galaxy Roles

  • Ansible Galaxy is a public library of Ansible content and contains thousands of roles that have been provided by community members.

Working with Galaxy

The easiest way to work with Ansible Galaxy is to use the website at https://galaxy.ansible.com:

Image Image

Image Image

  • Use the Search Feature to Search for Specific Packages

  • In the result of any Search action, you see a list of collections as well as a list of roles.

  • An Ansible Galaxy collection is a distribution format for Ansible content.

  • It can contain roles, but also playbooks, modules, and plug-ins.

  • In most cases you just need the roles, not the collection: roles contain all that you include in the playbooks you’re working with.

  • Some important indicators are the number of times the role has been downloaded and the score of the role.

  • This information enables you to easily distinguish between commonly used roles and roles that are not used that often.

  • Also, you can use tags to make identifying Galaxy roles easier.

  • These tags provide more information about a role and make it possible to search for roles in a more efficient way.

Image Image

  • You can download roles directly from the Ansible Galaxy website
  • You can also use the ansible-galaxy command

Using the ansible-galaxy Command

ansible-galaxy search

  • Find roles based on many different keywords and manage them.
  • Must provide a string as an argument.
  • Ansible searches for this string in the name and description of the roles.

Useful Command-Line Options: –platforms

  • Operating system platform to search for –author
  • GitHub username of the author –galaxy-tags
  • Additional tags to filter by

`ansible-galaxy info

  • Get more information about a role.
[ansible@control ansible-lab]$ ansible-galaxy info geerlingguy.docker

Role: geerlingguy.docker
        description: Docker for Linux.
        commit: 9115e969c1e57a1639160d9af3477f09734c94ac
        commit_message: Merge pull request #501 from adamus1red/adamus1red/alpine-compose

add compose package to Alpine specific variables
        created: 2023-05-08T20:49:45.679874Z
        download_count: 23592264
        github_branch: master
        github_repo: ansible-role-docker
        github_user: geerlingguy
        id: 10923
        imported: 2025-03-24T00:01:45.901567
        modified: 2025-03-24T00:01:47.840887Z
        path: ('/home/ansible/.ansible/roles', '/usr/share/ansible/roles', '/etc/ansible/roles')
        upstream_id: None
        username: geerlingguy

Managing Ansible Galaxy Roles

ansible-galaxy install

  • Install a role
  • normally installs the role into the ~/.ansible/roles directory because this role is specified in the role_path setting in ansible.cfg.
  • If you want roles to be installed in another directory, consider changing this parameter. -p
  • option to install the role to a different role path directory.

requirements file.

  • YAML file that you can include when using the ansible-roles command.
    - src: geerlingguy.nginx
      version: "2.7.0"
  • possible to add roles from sources other than Ansible Galaxy, such as a Git repository or a tarball.
  • In that case, you must specify the exact URL to the role using the src option.
  • When you are installing roles from a Git repository, the scm keyword is also required and must be set to git.

To install a role using the requirements file, you can use the -r option with the ansible-galaxy install command: ansible-galaxy install -r roles/requirements.yml

ansible-galaxy list

  • Get a list of currently installed roles

ansible-galaxy remove

  • Remove roles from your system.

LAB: Using ansible-galaxy to Manage Roles

  • Type ansible-galaxy search --author geerlingguy --platforms EL to see a list of roles that geerlingguy has created.
  • Make the command more specific and type ansible-galaxy search nginx --author geerlingguy --platforms EL to find the geerlingguy.nginx role.
  • Request more information about this role by using ansible-galaxy info geerlingguy.nginx.
  • Create a requirements file with the name listing96.yaml and give this file the following contents:
- src: geerlingguy.nginx
  version: "2.7.0"
  • Add the line roles_path = /home/ansible/roles to the ansible.cfg file.

  • Use the command ansible-galaxy install -r listing96.yaml to install the role from the requirements file. It is possible that by the time you run this exercise, the specified version 2.7.0 is no longer available. If that is the case, use ansible-galaxy info again to find a version that still is available, and change the requirements file accordingly.

  • Type ansible-galaxy list to verify that the new role was successfully installed on your system.

  • Write a playbook with the name exercise92.yaml that uses the role and has the following contents:

---
- name: install nginx using Galaxy role
  hosts: ansible2
  roles:
  - geerlingguy.nginx
  • Run the playbook using ansible-playbook exercise92.yaml and observe that the new role is installed from the custom roles path.

Ansible Roles

Work with roles and Create roles

Using Ansible Roles

  • Ready-to-use playbook-based Ansible solutions that you can easily include in your own playbooks.
  • Community roles are provided through Ansible Galaxy
  • Also possible to create your own roles.
  • Red Hat provides RHEL System Roles.
  • Roles make it possible to provide Ansible code in a reusable way.
  • You can easily define a specific task in a role, and after defining it in a role, you can easily redistribute that and ensure that tasks are handled the same way, no matter where they are executed.
  • Roles can be custom-made for specific environments, or default roles provided from Ansible Galaxy can be used.

Understanding Ansible Roles

  • work with include files.
  • All the different components that you may use in a playbook are used in roles and stored in separate directories.
  • While defining the role, you don’t need to tell the role that it should look in some of these specific directories; it does that automatically.
  • The only thing you need to do is tell your Ansible playbook that it should include a role.
  • Different components of the role are stored in different subdirectories.

Roles Sample Directory Structure:

    [ansible@control roles]$ tree testrole/
    testrole/
    |-- defaults
    |   `-- main.yml
    |-- files
    |-- handlers
    |   `-- main.yml
    |-- meta
    |   `-- main.yml
    |-- README.md
    |-- tasks
    |   `-- main.yml
    |-- templates
    |-- tests
    |   |-- inventory
    |   `-- test.yml
    `-- vars
        `-- main.yml

Role Directory Structure defaults

  • Default variables that may be overwritten by other variables files

  • Static files that are needed by role tasks handlers

  • Handlers for use in this role meta

  • metadata, such as dependencies, plus license and maintainer information tasks

  • Role task definitions templates

  • Jinja2 templates tests

  • Optional inventory and a test.yml file to test the role vars

  • Variables that are not meant to be overwritten

  • Most of the role directories have a main.yml file.

  • This is the entry-point YAML file that is used to define components in the role.

Understanding Role Location

Roles can be stored in different locations:

./roles

  • store roles in the current project directory.
  • highest precedence.

~/.ansible/roles

  • exists in the current user home directory and makes the role available to the current user only.
  • second-highest precedence.

/etc/ansible/roles

  • Where roles are stored to make them accessible to any user.

/usr/share/ansible/roles

  • Where roles are stored after they are installed from RPM files.
  • lowest precedence
  • should not be used for storing custom-made roles.

ansible-galaxy init { newrolename }

  • create a custom role
  • creates the default role directory structure with a main.yml file
  • includes sample files

Using Roles from Playbooks

  • Call roles in a playbook the same way you call a task
  • Roles are included as a list.
    ---
    - name: include some roles
      roles:
      - role1
      - role2
  • Roles are executed before the tasks.
  • In specific cases you might have to execute tasks before the roles. To do so, you can specify these tasks in a pre_tasks section.
  • Also, it’s possible to use the post_tasks section to include tasks that will be executed after the roles, but also after tasks specified in the playbook as well as the handlers they call.

Creating Custom Roles

  • Use mkdir roles to create a roles subdirectory in the current directory, and use cd roles to get into that subdirectory.
  • Use ansible-galaxy init motd to create the motd role structure.
  • Add contents to motd/tasks/main.yml
  • Add contents to motd/templates/motd.j2
  • Add contents to motd/defaults/main.yml
  • Add contents to motd/meta/main.yml
  • Create the playbook exercise91.yaml to run the role
  • Run the playbook by using ansible-playbook exercise91.yaml
  • Verify that modifications have been applied correctly by using the ad hoc command ansible ansible2 -a "cat /etc/motd"

Sample role all under roles/motd/:

defaults/main.yml

---
# defaults file for motd
system_manager: anna@example.com

meta/main.yml

galaxy_info:
author: Sander van V
description: your description
company: your company (optional)
license: license (GPLv2, CC-BY, etc)
min_ansible_version: 2.5

tasks/main.yml

---
tasks file for motd
- name: copy motd file
  template:
    src: templates/motd.j2
    dest: /etc/motd
    owner: root
    group: root
    mode: 0444

templates/motd.j2

Welcome to {{ ansible_hostname }}
    
This file was created on {{ ansible_date_time.date }}
Disconnect if you have no business being here
    
Contact {{ system_manager }} if anything is wrong

Playbook motd.yml:

---
- name: use the motd role playbook
  hosts: ansible2
  roles:
  - role: motd
    system_manager: bob@example.com

handlers/main.yml example:

---
# handlers file for base-config
  - name: source profile
    command: source /etc/profile

  - name: source bash
    command: source /etc/bash.bashrc                               

Managing Role Dependencies

  • Roles may use other roles as a dependency.
  • You can put role dependencies in meta/main.yml
  • Dependent roles are always executed before the roles that depend on them.
  • Dependent roles are executed once.
  • When two roles that are used in a playbook call the same dependency, the dependent role is executed once only.
  • When calling dependent roles, it is possible to pass variables to the dependent role.
  • You can define a when statement to ensure that the dependent role is executed only in specific situations.

Defining dependencies in meta/main.yml

    dependencies:
    - role: apache
      port: 8080
    - role: mariabd
      when: environment == ’production’

Understanding File Organization Best Practices

  • Working with roles splits the contents of the role off the tasks that are run through the playbook.

  • Splitting files to store them in a location that makes sense is common in Ansible

  • When you’re working with Ansible, it’s a good idea to work with project directories in bigger environments.

  • Working with project directories makes it easier to delegate tasks and have the right people responsible for the right things.

  • Each project directory may have its own ansible.cfg file, inventory file, and playbooks.

  • If the project grows bigger, variable files and other include files may be used, and they are normally stored in subdirectories.

  • At the top-level directory, create the main playbook from which other playbooks are included. The suggested name for the main playbook is site.yml.

  • Use group_vars/ and host_vars/ to set host-related variables and do not define them in inventory.

  • Consider using different inventory files to differentiate between production and staging phases.

  • Use roles to standardize common tasks.

When you are working with roles, some additional recommendations apply:

  • Use a version control repository to maintain roles in a consistent way. Git is commonly used for this purpose.

  • Sensitive information should never be included in roles. Use Ansible Vault to store sensitive information in an encrypted way.

  • Use ansible-galaxy init to create the role base structure. Remove files and directories you don’t use.

  • Don’t forget to provide additional information in the role’s README.md and meta/main.yml files.

  • Keep roles focused on a specific function. It is better to use multiple roles to perform multiple tasks.

  • Try to develop roles in a generic way, such that they can be used for multiple purposes.

Lab 9-1

Create a playbook that starts the Nginx web server on ansible1, according to the following requirements: • A requirements file must be used to install the Nginx web server. Do NOT use the latest version of the Galaxy role, but instead use the version before that. • The same requirements file must also be used to install the latest version of postgresql. • The playbook needs to ensure that neither httpd nor mysql is currently installed.

Lab 9-2

Use the RHEL SELinux System Role to manage SELinux properties according to the following requirements:

• A Boolean is set to allow SELinux relabeling to be automated using cron. • The directory /var/ftp/uploads is created, permissions are set to 777, and the context label is set to public_content_rw_t. • SELinux should allow web servers to use port 82 instead of port 80. • SELinux is in enforcing state. Subjects: ansible-playbook timesync.yaml to run the playbook. Observe its output. Notice that some messages in red are shown, but these can safely be ignored.

5. Use ansible ansible2 -a "timedatectl show" and notice that the timezone variable is set to UTC.

Lab 9-1

Create a playbook that starts the Nginx web server on ansible1, according to the following requirements: • A requirements file must be used to install the Nginx web server. Do NOT use the latest version of the Galaxy role, but instead use the version before that. • The same requirements file must also be used to install the latest version of postgresql. ansible-galaxy install -r roles/requirements.yml

cat roles/requirements.yml

- src: geerlingguy.nginx
  version: "3.1.4"

- src: geerlingguy.postgresql

• The playbook needs to ensure that neither httpd nor mysql is currently installed.

---
- name: ensure conflicting packages are not installed
  hosts: web1
  tasks:
  - name: remove packages
    yum:
      name: 
      - mysql
      - httpd
      state: absent

- name: nginx web server
  hosts: web1
  roles: 
  - geerlingguy.nginx
  - geerlingguy.postgresql

(Had to add a variable file for redhat 10 into the role. )

Lab 9-2

Use the RHEL SELinux System Role to manage SELinux properties according to the following requirements:

• A Boolean is set to allow SELinux relabeling to be automated using cron. • The directory /var/ftp/uploads is created, permissions are set to 777, and the context label is set to public_content_rw_t. • SELinux should allow web servers to use port 82 instead of port 80. • SELinux is in enforcing state.

vim lab92.yml

---
- name: manage ftp selinux properties
  hosts: ftp1
  vars:
    selinux_booleans: 
      - name: cron_can_relabel
        state: true
        persistent: true
    selinux_state: enforcing
    selinux_ports:
    - ports: 82
      proto: tcp
      setype: http_port_t
      state: present
      local: true
 
  tasks:

  - name: create /var/ftp/uploads/
    file:
      path: /var/ftp/uploads
      state: directory
      mode: 777
  
  - name: set selinux context
    sefcontext:
      target: '/var/ftp/uploads(/.*)?'
      setype: public_content_rw_t
      ftype: d
      state: present
    notify: run restorecon

  - name: Execute the role and reboot in a rescue block
    block:
      - name: Include selinux role
        include_role:
          name: rhel-system-roles.selinux
    rescue:
      - name: >-
          Fail if failed for a different reason than selinux_reboot_required
        fail:
          msg: "role failed"
        when: not selinux_reboot_required

      - name: Restart managed host
        reboot:

      - name: Wait for managed host to come back
        wait_for_connection:
          delay: 10
          timeout: 300

      - name: Reapply the role
        include_role:
          name: rhel-system-roles.selinux
  
  handlers:
    - name:  run restorecon
      command: restorecon -v /var/ftp/uploads

Using RHEL System roles

Using RHEL System Roles

  • Allows for a uniform approach while managing multiple RHEL versions
  • Red Hat provides RHEL System Roles.
  • RHEL System Roles make managing different parts of the operating system easy.

RHEL System Roles:

rhel-system-roles.kdump

  • Configures the kdump crash recovery service rhel system-roles.network
  • Configures network interfaces rhel system-roles.postfix
  • Configures hosts as a Mail Transfer Agent using Postfix rhel system-roles.selinux
  • Manages SELinux settings rhel system-roles.storage
  • Configures storage rhel system-roles.timesync
  • Configures time synchronization

Understanding RHEL System Roles

  • RHEL System Roles are based on the community Linux System Roles
  • Provide a uniform interface to make configuration tasks easier where significant differences may exist between versions of the managed operating system.
  • RHEL System Roles can be used to manage Red Hat Enterprise Linux 6.10 and later, as well as RHEL 7.4 and later, and all versions of RHEL 8.
  • Linux System Roles are not supported by RHEL technical support.

Installing RHEL System Roles

  • To use RHEL System Roles, you need to install the rhel-system-roles package on the control node by using sudo yum install rhel-system-roles.

  • This package can be found in the RHEL 8 AppStream repository.

  • After installation, the roles are copied to the /usr/share/ansible/roles directory, a directory that is a default part of the Ansible roles_path setting.

  • If a modification to the roles_path setting has been made in ansible.cfg, the roles are applied to the first directory listed in the roles_path.

  • With the roles, some very useful documentation is installed also; you can find it in the /usr/share/doc/rhel-system-roles directory.

  • To pass configuration to the RHEL System Roles, variables are important.

  • In the documentation directory, you can find information about variables that are required and used by the role.

  • Some roles also contain a sample playbook that can be used as a blueprint when defining your own role.

  • It’s a good idea to use these as the basis for your own RHEL System Roles–based configuration.

  • The next two sections describe the SELinux and the TimeSync System Roles, which provide nice and easy-to-implement examples of how you can use the RHEL System Roles.

Using the RHEL SELinux System Role

  • You learned earlier how to manage SELinux settings using task definitions in your own playbooks.

  • Using the RHEL SELinux System Role provides an easy-to-use alternative.

  • To use this role, start by looking at the documentation, which is in the /usr/share/doc/rhel-system-roles/selinux directory.

  • A good file to start with is the README.md file, which provides lists of all the ingredients that can be used.

  • The SELinux System Role also comes with a sample playbook file.

  • The most important part of this file is the vars: section, which defines the variables that should be applied by SELinux.

Variable Definition in the SELinux System Role:

    ---
    - hosts: all
      become: true
      become_method: sudo
      become_user: root
      vars:
        selinux_policy: targeted
        selinux_state: enforcing
        selinux_booleans:
          - { name: ’samba_enable_home_dirs’, state: ’on’ }
          - { name: ’ssh_sysadm_login’, state: ’on’, persistent: ’yes’ }
        selinux_fcontexts:
          - { target: ’/tmp/test_dir(/.*)?’, setype: ’user_home_dir_t’, ftype: ’d’ }
        selinux_restore_dirs:
          - /tmp/test_dir
        selinux_ports:
          - { ports: ’22100’, proto: ’tcp’, setype: ’ssh_port_t’, state: ’present’ }
        selinux_logins:
          - { login: ’sar-user’, seuser: ’staff_u’, serange: ’s0-s0:c0.c1023’, state: ’present’ }

SELinux Variables Overview

selinux_policy

  • Policy to use, usually set to targeted selinux_state

  • SELinux state, as managed with setenforce selinux_booleans

  • List of Booleans that need to be set selinux_fcontext

  • List of file contexts that need to be set, including the target file or directory to which they should be applied. selinux_restore_dir

  • List of directories at which the Linux restorecon command needs to be executed to apply new context. selinux_ports

  • List of ports and SELinux port types selinux_logins

  • A list of SELinux user and roles that can be created

  • Most of the time while configuring SELinux, you need to apply the correct state as well as file context.

  • To set the appropriate file context, you first need to define the selinux_fcontext variable.

  • Next, you have to define selinux_restore_dirs also to ensure that the desired context is applied correctly.

Lab: Sets the httpd_sys_content_t context type to the /web directory.

  • Sample doc is used and unnecessary lines are removed and the values of two variables have been set
  • When you use the RHEL SELinux System Role, some changes require the managed host to be rebooted.
  • To take care of this, a block structure is used, where the System Role runs in the block.
  • When a change that requires a reboot is applied, the SELinux System Role sets the variable selinux_reboot_required and fails.
  • As a result, the rescue section in the playbook is executed.
  • This rescue section first makes sure that the playbook fails because of the selinux_reboot_required variable being set to true.
  • If that is the case, the reboot module is called to reboot the managed host.
  • While rebooting, playbook execution waits for the rebooted host to reappear, and when that happens, the RHEL SELinux System Role is called again to complete its work.
---
- hosts: ansible2
  vars:
    selinux_policy: targeted
    selinux_state: enforcing
    selinux_fcontexts:
      - { target: ’/web(/.*)?’, setype: ’httpd_sys_content_t’, ftype: ’d’ }
    selinux_restore_dirs:
      - /web
    
# prepare prerequisites which are used in this playbook
  tasks:
    - name: Creates directory
        file:
        path: /web
        state: directory
    - name: execute the role and catch errors
        block:
        - include_role:
            name: rhel-system-roles.selinux
        rescue:
            # Fail if failed for a different reason than selinux_reboot_required.
            - name: handle errors
              fail:
                msg: "role failed"
              when: not selinux_reboot_required
    
            - name: restart managed host
              shell: sleep 2 && shutdown -r now "Ansible updates triggered"
              async: 1
              poll: 0
              ignore_errors: true
    
            - name: wait for managed host to come back
              wait_for_connection:
                delay: 10
                timeout: 300
    
            - name: reapply the role
              include_role:
                name: rhel-system-roles.selinux

Using the RHEL TimeSync System Role

timesync_ntp_servers variable

  • most important setting

  • specifies attributes to indicate which time servers should be used.

  • The hostname attribute identifies the name of IP address of the time server.

  • The iburst option is used to enable or disable fast initial time synchronization using the timesync_ntp_servers variable.

  • The System Role finds out which version of RHEL is used, and according to the currently used version, it either configures NTP or Chronyd.

Lab: Using an RHEL System Role to Manage Time Synchronization

1. Copy the sample timesync playbook to the current directory: cp /usr/share/doc/rhel-system-roles/timesync/example-single-pool-playbook.yml timesync.yaml

2. Add the target host, NTP hostname pool.ntp.org, and remove pool true in the file timesync.yaml:

---
- name: Configure NTP
  hosts: "{{ host }}"
  vars:
    timesync_ntp_servers:
      - hostname: pool.ntp.org
        iburst: true
  roles:
    - rhel-system-roles.timesync

3. Add the timezone module and the timezone variable to the playbook to set the timezone as well. The complete playbook should look like the following:

---
- hosts: ansible2
  vars:
    timesync_ntp_servers:
    - hostname: pool.ntp.org
      iburst: yes
    timezone: UTC
  roles:
  - rhel-system-roles.timesync
  tasks:
  - name: set timezone
    timezone:
      name: "{{ timezone }}"

4. Use ansible-playbook timesync.yaml to run the playbook. Observe its output. Notice that some messages in red are shown, but these can safely be ignored.

5. Use ansible ansible2 -a "timedatectl show" and notice that the timezone variable is set to UTC.