Ansible Collections and RHEL System Roles Explained

Learn Ansible collections, FQCN module names, ansible-galaxy collection install, collection requirements.yml, and RHEL System Roles examples for timesync, network, SELinux, storage, and firewall.

Published

Updated

Read time 11 min read

Reviewed byDeepak Prasad

Ansible collections, FQCN, and RHEL System Roles on Rocky Linux 10

Standalone Galaxy roles live under roles/ and are installed with ansible-galaxy role install. Collections are the modern packaging format: modules, plugins, roles, and docs grouped under a namespace such as ansible.posix or redhat.rhel_system_roles. RHEL System Roles provide Red Hat-supported automation for time sync, networking, SELinux, storage, firewall, and other system configuration on RHEL—and the same collection is often packaged on Rocky Linux for lab and automation use.

Tested on: Rocky Linux 10.2 (Red Quartz); kernel 6.12.0-211.16.1.el10_2.0.1.x86_64; ansible-core 2.16.16; redhat.rhel_system_roles 1.120.5 (from rhel-system-roles RPM).

IMPORTANT
redhat.rhel_system_roles is Red Hat's supported collection for RHEL. Rocky Linux and AlmaLinux often package the same or closely related content as the rhel-system-roles RPM, but Red Hat support and release cadence apply to RHEL subscriptions—not necessarily to every Rocky minor release. Before you rely on a role in production, run dnf provides '*/redhat/rhel_system_roles' or ansible-galaxy collection list redhat.rhel_system_roles on your control node and pin the version in requirements.yml.
NOTE
This chapter is part of the GoLinuxCloud Ansible tutorial (RHCE EX294). Follow along from ~/ansible-project, inventory group lab, and playbooks in playbooks/. Use your own host names and paths if yours differ.
Feature Role Collection
Main purpose Reusable automation structure Package and distribute Ansible content
Can contain tasks Yes Yes, through roles and playbooks
Can contain modules/plugins No (not normally) Yes
Has namespace No Yes (namespace.collection)
Installed with Galaxy ansible-galaxy role install ansible-galaxy collection install
Example roles/webserver community.general, ansible.posix, redhat.rhel_system_roles

What are Ansible Collections?

A collection is a content bundle identified by namespace.collection—for example ansible.posix or community.crypto. Inside you may find:

  • Modules and plugins under plugins/
  • Roles under roles/
  • Playbooks under playbooks/
  • Documentation under docs/
  • Metadata in galaxy.yml / MANIFEST.json

Galaxy and Automation Hub publish collections as versioned artifacts. After install, Ansible searches collections_path and resolves content by FQCN—set that path in ansible.cfg when collections live beside the project. Module discovery with ansible-doc is covered in modules and ansible-doc.

Official overview: Using Ansible collections.


Why Ansible Uses Collections

Before collections, many modules shared a flat global name—copy, yum, firewalld—and naming collisions grew as the ecosystem expanded. Collections add:

  • Namespacingansible.builtin.copy vs a third-party copy
  • Versioning — pin community.crypto:2.22.0 in CI
  • Packaging — ship modules, plugins, roles, and docs together
  • Distribution — Galaxy, private Hub, or RPM (ansible-collection-*, rhel-system-roles)

For exam and production playbooks, prefer FQCN so Ansible always loads the module or role you intend.


Roles vs Collections in Ansible

Role Collection
Unit of reuse One stack (web, db, timesync) Many resources under one namespace
Typical install path roles/webserver/ ansible_collections/<namespace>/<collection>/
Playbook reference roles: [webserver] ansible.posix.mount or redhat.rhel_system_roles.timesync
Contains modules No Often yes

A collection can contain roles. RHEL System Roles ships dozens of roles inside redhat.rhel_system_roles—you call them with the collection role name, not a separate roles/ directory install.


What is FQCN in Ansible?

FQCN (Fully Qualified Collection Name) is namespace.collection.name:

Short name FQCN example Why use FQCN
copy ansible.builtin.copy Built-in module in the ansible.builtin collection
firewalld ansible.posix.firewalld Avoids ambiguity with other firewall modules
timesync role redhat.rhel_system_roles.timesync Shows the role comes from the system roles collection

In playbooks, FQCN applies to modules:

yaml
- name: Deploy file with built-in copy module
  ansible.builtin.copy:
    src: app.conf
    dest: /etc/app/app.conf
    mode: "0644"

Ansible 2.10+ still resolves some short names for backward compatibility, but playbooks and exams expect FQCN for clarity and stability.

The collections: keyword in a playbook does not install collections—it only changes lookup behavior for short names. For tutorials, CI, and troubleshooting, FQCN remains clearer than relying on implicit collection search order.


Install Ansible Collections

List what is already available:

bash
ansible-galaxy collection list

Sample output:

output
# /home/ansible/.ansible/collections/ansible_collections
Collection               Version
------------------------ -------
community.crypto         2.22.0
community.general        9.5.2

# /usr/share/ansible/collections/ansible_collections
Collection               Version
------------------------ -------
ansible.posix            2.1.0
redhat.rhel_system_roles 1.120.5

Install one collection into your user path:

bash
ansible-galaxy collection install community.crypto:2.22.0 -p ~/.ansible/collections --force

Sample output:

output
Starting galaxy collection install process
Installing 'community.crypto:2.22.0' to '/home/ansible/.ansible/collections/ansible_collections/community/crypto'
community.crypto:2.22.0 was installed successfully

Pin the version (:2.22.0) when you need reproducible CI installs.


Install Collections with requirements.yml

Use a collections key—different from the plain role list in the Galaxy roles guide:

yaml
---
collections:
  - name: community.crypto
    version: "2.22.0"

Install from the file:

bash
ansible-galaxy collection install -r collections-requirements.yml -p ~/.ansible/collections --force

Sample output:

output
Starting galaxy collection install process
Installing 'community.crypto:2.22.0' to '/home/ansible/.ansible/collections/ansible_collections/community/crypto'
community.crypto:2.22.0 was installed successfully

A combined project file can list both artifact types:

yaml
---
collections:
  - name: ansible.posix
    version: "2.1.0"
roles:
  - name: geerlingguy.nginx
    version: "3.2.0"

Install both with the generic command:

bash
ansible-galaxy install -r requirements.yml

Sample output:

output
Starting galaxy role install process
- geerlingguy.nginx (3.2.0) was installed successfully
Starting galaxy collection install process
Nothing to do. All requested collections are already installed.

If you use custom install paths with -p, keep role and collection requirement files separate. ansible-galaxy collection install -r installs only collections, and ansible-galaxy role install -r installs only roles—a combined file with -p can skip collections per the official docs.


Use Modules from Collections

Ad-hoc check with FQCN:

bash
cd ~/ansible-project
bash
ansible rocky2 -m ansible.builtin.ping

Sample output:

output
rocky2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

ansible.builtin is the built-in collection shipped with ansible-core. External collections follow the same pattern—ansible.posix.mount, community.general.sefcontext, and so on.

Confirm where Ansible searches:

bash
ansible-config dump | grep COLLECTIONS_PATH

Sample output:

output
COLLECTIONS_PATHS(/home/ansible/ansible-project/ansible.cfg) = ['/home/ansible/.ansible/collections', '/usr/share/ansible/collections']

If a playbook fails with “couldn’t resolve module/action”, the collection is usually missing from collections_path or the play uses a short name that no longer resolves.

If a collection is installed but Ansible still cannot find it, compare these two commands:

bash
ansible-galaxy collection list community.crypto

Sample output:

output
# /home/ansible/.ansible/collections/ansible_collections
Collection       Version
---------------- -------
community.crypto 2.22.0
bash
ansible-config dump | grep COLLECTIONS_PATH

Sample output:

output
COLLECTIONS_PATHS(/home/ansible/ansible-project/ansible.cfg) = ['/home/ansible/.ansible/collections', '/usr/share/ansible/collections']

The collection must be installed under one of the paths Ansible is actually using.

Inspect collection documentation

Module docs live in ansible-doc:

bash
ansible-doc ansible.builtin.copy

Sample output:

output
> ANSIBLE.BUILTIN.COPY    (/usr/lib/python3.12/site-packages/ansible/modules/copy.py)

        The [ansible.builtin.copy] module copies a file or a directory
        structure from the local or remote machine to a location on
        the remote machine.
bash
ansible-doc ansible.posix.firewalld

For collection roles, read the installed role README—variable names, defaults, and warnings are documented there:

bash
less /usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/README.md

Use Roles from Collections

Do not copy collection roles into your project roles/ directory. Reference them by FQCN, such as redhat.rhel_system_roles.timesync, and let Ansible load them from ansible_collections/<namespace>/<collection>/roles/.

Collection roles use namespace.collection.role_name in the play:

yaml
---
- name: Configure NTP with RHEL System Roles
  hosts: rocky2
  become: true
  roles:
    - redhat.rhel_system_roles.timesync
  vars:
    timesync_ntp_servers:
      - hostname: pool.ntp.org
        iburst: true

Run a dry run first—system roles can replace service configuration:

bash
ansible-playbook timesync.yml --check

Sample output:

output
TASK [redhat.rhel_system_roles.timesync : Enable chronyd] **********************
ok: [rocky2]

RUNNING HANDLER [redhat.rhel_system_roles.timesync : Restart chronyd] **********
changed: [rocky2]

PLAY RECAP *********************************************************************
rocky2                     : ok=22   changed=4    unreachable=0    failed=0    skipped=30   rescued=0    ignored=0

The redhat.rhel_system_roles.timesync : prefix in task names shows the collection role Ansible loaded.


Collection Directory Structure

After install, a collection lives under ansible_collections/<namespace>/<collection>/. A typical layout:

text
community/crypto/
├── meta/
├── plugins/
│   ├── modules/
│   ├── module_utils/
│   └── lookup/
├── docs/
├── roles/          # if the collection ships roles
└── galaxy.yml      # or MANIFEST.json for built artifacts

You rarely edit files under ansible_collections/—treat them like vendor code and upgrade with ansible-galaxy collection install --force.


What are RHEL System Roles?

RHEL System Roles are Red Hat-supported Ansible roles, modules, and playbooks for consistent RHEL administration: time synchronization, networking, SELinux, storage, firewall, logging, and more. Rocky Linux 10 packages the same collection as rhel-system-roles, installing redhat.rhel_system_roles under /usr/share/ansible/collections/.

Role Use case
timesync NTP/PTP time synchronization (chrony, ntp, linuxptp)
network NetworkManager connection profiles
selinux SELinux mode, policy, booleans, ports, contexts (role scope)
storage Disks, volumes, filesystems
firewall Firewall configuration
logging Rsyslog/journald logging stack

For small playbook-level examples using the sefcontext module directly, see SELinux file contexts with Ansible.


RHEL System Roles vs Linux System Roles

Linux System Roles RHEL System Roles
Origin Upstream linux-system-roles community project Red Hat-supported downstream packaging
Collection name Often fedora.linux_system_roles on Galaxy redhat.rhel_system_roles
Support Community Red Hat (RHEL); Rocky/Alma may ship related packages without Red Hat support
RPM on Rocky/RHEL Related content may appear under /usr/share/ansible/roles/linux-system-roles.* dnf install rhel-system-roles

Playbook syntax is the same pattern: namespace.collection.role. On this lab, use redhat.rhel_system_roles.<role> after installing the RPM.


Install RHEL System Roles

Install rhel-system-roles on the Ansible control node, or bake it into the automation execution environment used to run the playbook. Managed hosts do not need the collection installed unless they also run Ansible locally.

On RHEL, Rocky Linux, or AlmaLinux:

bash
sudo dnf install rhel-system-roles

Verify the collection appears:

bash
ansible-galaxy collection list | grep rhel_system_roles

Sample output:

output
redhat.rhel_system_roles 1.120.5

Alternative: install from Galaxy or Automation Hub when you are not using the distro package:

bash
ansible-galaxy collection install redhat.rhel_system_roles

Red Hat customers often pull from Automation Hub; the playbook role names stay redhat.rhel_system_roles.*.


Use a RHEL System Role in a Playbook

Common pattern:

yaml
---
- name: Apply a system role
  hosts: managed
  become: true
  roles:
    - redhat.rhel_system_roles.<role_name>
  vars:
    # role-specific variables from upstream README

Read each role's README under /usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/<role>/ for variable names and warnings—many roles replace entire configuration files when applied.


Common RHEL System Role Examples

Configure time synchronization with timesync

yaml
---
- name: Sync time with chrony
  hosts: rocky2
  become: true
  roles:
    - redhat.rhel_system_roles.timesync
  vars:
    timesync_ntp_servers:
      - hostname: pool.ntp.org
        iburst: true

The role selects chrony, ntp, or linuxptp based on variables and managed host state. Review the role README before production—undefined variables still trigger a full config replacement for the chosen provider.

Configure networking with network role

Use the interface name from facts (ansible_default_ipv4.interface on this lab is enp0s3):

yaml
---
- name: Ensure connection is up
  hosts: rocky2
  become: true
  roles:
    - redhat.rhel_system_roles.network
  vars:
    network_connections:
      - name: enp0s3
        type: ethernet
        interface_name: enp0s3
        state: up

A wrong interface_name fails fast—the role expects a real NetworkManager interface on the host. For remote hosts, be extra careful with the network role: a valid but wrong connection profile can interrupt SSH access. Test from console access or a disposable VM before applying it to production.

Configure SELinux with selinux role

yaml
---
- name: Enforce SELinux
  hosts: rocky2
  become: true
  roles:
    - redhat.rhel_system_roles.selinux
  vars:
    selinux_state: enforcing

The system role can manage SELinux state, booleans, ports, file contexts, logins, modules, and restore operations. For small playbook-level examples using the sefcontext module directly, see SELinux file contexts with Ansible.

Configure storage or firewall roles

Structure is the same—swap the role name and variables from the upstream README:

yaml
roles:
  - redhat.rhel_system_roles.firewall
# vars per firewall README — services, ports, zones

roles:
  - redhat.rhel_system_roles.storage
# vars per storage README — pools, volumes, filesystems

Storage and firewall roles carry more destructive potential than timesync. Always run --check and read the role warning blocks first.


Collections vs Galaxy Roles: Practical Difference

Task Galaxy standalone role Collection
Install command ansible-galaxy role install author.nginx -p roles/ ansible-galaxy collection install community.crypto
Requirements file key Plain list (- name: author.nginx) collections: list
On disk roles/author.nginx/ ansible_collections/community/crypto/
Module access Uses collections separately Modules bundled in same package
RHEL system config Uncommon for OS baseline redhat.rhel_system_roles.*

Use standalone Galaxy roles for community app stacks (web servers, databases). Use collections for namespaced modules and for RHEL System Roles that encode supported OS configuration.


Common Mistakes

Mistake Why it hurts
Using short module names only Breaks when collections change or ambiguity warnings become errors
Forgetting to install the collection couldn't resolve module/action at runtime
Mixing up role vs collection requirements syntax ansible-galaxy role install ignores collections: keys; combined file + -p can skip collections
Calling timesync instead of redhat.rhel_system_roles.timesync Ansible cannot find the role in roles_path
Editing files under ansible_collections/ Next install overwrites local patches
Skipping role README warnings System roles replace whole config files—surprising downtime
Wrong network interface_name network role fails when NM has no matching device

Best Practices

Practice Why
Use FQCN for modules and collection roles Clear source; exam-aligned
Pin collection versions in requirements.yml Reproducible CI and production
Keep collections_path in ansible.cfg Playbooks and ad-hoc commands agree on search paths
Install rhel-system-roles on the control node or execution environment Collection must be present where ansible-playbook runs—not on every managed host
Run --check before system roles Surfaces interface and SELinux mistakes early
Read role README and defaults before first apply Documents required variables and side effects
Separate vendor collections from custom roles/ Clean git boundaries

Summary

Collections package Ansible content under namespace.collection, installed with ansible-galaxy collection install and declared in requirements.yml under collections:. FQCN (ansible.builtin.copy, community.general.sefcontext, redhat.rhel_system_roles.timesync) removes naming ambiguity. RHEL System Roles deliver supported OS configuration roles inside redhat.rhel_system_roles—install via rhel-system-roles RPM or Galaxy. Standalone Galaxy roles and role directory layout remain the foundation; collections are how modules and system roles are distributed at scale.


References

  • Using Ansible collections — install paths and FQCN
  • Installing collectionsansible-galaxy collection install
  • Collection structure — directory layout
  • Managing systems using RHEL System Roles — Red Hat documentation
  • Linux System Roles — upstream community project
  • Create and install Galaxy roles — standalone role workflow
  • Ansible roles explained — role tree and variables
  • SELinux file contexts — sefcontext in custom playbooks

Frequently Asked Questions

1. What is the difference between an Ansible role and a collection?

A role is a reusable task and variable bundle. A collection is a distribution package that can contain roles, modules, plugins, and docs under a namespace such as community.general or redhat.rhel_system_roles.

2. What is FQCN in Ansible?

Fully Qualified Collection Name—namespace.collection.resource, for example ansible.builtin.copy or redhat.rhel_system_roles.timesync. FQCN tells Ansible exactly which collection provides the module or role.

3. What is the difference between RHEL System Roles and Linux System Roles?

Linux System Roles is the upstream community project. RHEL System Roles is the Red Hat-supported downstream content for RHEL, shipped as the redhat.rhel_system_roles collection. RHEL-compatible distributions such as Rocky Linux may package the same or closely related content, but Red Hat support applies to RHEL.

4. How do I install Ansible collections?

Run ansible-galaxy collection install namespace.collection, or declare collections in a requirements.yml file and install with ansible-galaxy collection install -r requirements.yml -p path/.

5. Can I mix role and collection requirements in one file?

Yes—use roles: and collections: keys in one requirements.yml and run ansible-galaxy install -r requirements.yml. If you pass custom -p install paths, keep separate files and use ansible-galaxy role install -r and ansible-galaxy collection install -r instead.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …