Introduction
The ansible.builtin.yum and ansible.builtin.dnf modules manage packages on Red Hat family systems — RHEL, CentOS, CentOS Stream, Fedora, Oracle Linux, Rocky Linux, and AlmaLinux. They handle installation, updates, removal, group installs, and repository management in idempotent tasks.
yum vs dnf — Which Module to Use?
| OS | Native Package Manager | Recommended Module |
|---|---|---|
| RHEL/CentOS 7 | yum | ansible.builtin.yum |
| RHEL 8/9 | dnf | ansible.builtin.dnf |
| CentOS Stream 8/9 | dnf | ansible.builtin.dnf |
| Fedora | dnf | ansible.builtin.dnf |
| Rocky/Alma Linux | dnf | ansible.builtin.dnf |
Cross-platform: ansible.builtin.package auto-detects the right module.
Module Parameters
| Parameter | Type | Description |
|---|---|---|
name | list/string | Package name(s) to manage |
state | string | present, latest, absent, installed, removed |
update_cache | bool | Refresh repo metadata before install |
enablerepo | string | Enable specific repo for this transaction |
disablerepo | string | Disable specific repo for this transaction |
exclude | string | Packages to exclude |
skip_broken | bool | Skip packages with dependency issues |
allow_downgrade | bool | Allow installing older version |
security | bool | Only install security updates |
bugfix | bool | Only install bugfix updates |
lock_timeout | int | Seconds to wait for lock (dnf only) |
install_weak_deps | bool | Install weak dependencies (dnf only) |
Basic Operations
Install a Package
- name: Install wget
ansible.builtin.yum:
name: wget
state: present
Install Multiple Packages
- name: Install common tools
ansible.builtin.yum:
name:
- wget
- curl
- vim
- git
- htop
- tree
state: present
Install a Specific Version
- name: Install specific wget version
ansible.builtin.yum:
name: wget-1.19.5-7.el8
state: present
allow_downgrade: true
Update a Package
- name: Update nginx to latest
ansible.builtin.yum:
name: nginx
state: latest
Update All Packages
- name: Update all packages
ansible.builtin.yum:
name: "*"
state: latest
security: true # Only security updates
Remove a Package
- name: Remove old package
ansible.builtin.yum:
name: httpd
state: absent
autoremove: true # Remove unused dependencies
Install from Local RPM or URL
# Install from URL
- name: Install Chrome from URL
ansible.builtin.yum:
name: https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
state: present
disable_gpg_check: true
# Install from local RPM
- name: Install local package
ansible.builtin.yum:
name: /tmp/mypackage-1.0.rpm
state: present
Repository Management
Enable/Disable Repos for a Transaction
- name: Install from EPEL
ansible.builtin.yum:
name: htop
state: present
enablerepo: epel
- name: Install without testing repo
ansible.builtin.yum:
name: nginx
state: present
disablerepo: "testing*"
Add a Repository
- name: Add EPEL repository
ansible.builtin.yum_repository:
name: epel
description: EPEL YUM repo
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: true
gpgkey: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{{ ansible_distribution_major_version }}
enabled: true
Refresh Cache
- name: Install with fresh cache
ansible.builtin.yum:
name: nginx
state: present
update_cache: true
Package Groups
# Install a package group
- name: Install Development Tools
ansible.builtin.yum:
name: "@Development Tools"
state: present
# DNF module syntax
- name: Install Development Tools (dnf)
ansible.builtin.dnf:
name: "@development"
state: present
Cross-Platform Patterns
Using the package Module
# Works on RHEL, Debian, SUSE — auto-detects package manager
- name: Install nginx (any distro)
ansible.builtin.package:
name: nginx
state: present
OS-Specific Package Names
- name: Install Apache
ansible.builtin.package:
name: "{{ apache_package }}"
state: present
vars:
apache_package: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}"
Variable-Driven Package List
# group_vars/redhat.yml
packages:
- httpd
- mod_ssl
- php
- php-mysqlnd
# playbook
- name: Install application stack
ansible.builtin.yum:
name: "{{ packages }}"
state: present
Error Handling
- name: Install with retry on failure
ansible.builtin.yum:
name: mypackage
state: present
register: yum_result
retries: 3
delay: 10
until: yum_result is not failed
Version Pinning with versionlock
- name: Install yum-plugin-versionlock
ansible.builtin.yum:
name: yum-plugin-versionlock
state: present
- name: Lock package version
community.general.yum_versionlock:
name: nginx-1.20.1
state: present
Practical Example: Web Server Setup
---
- name: Configure web server
hosts: web_servers
become: true
tasks:
- name: Install web server packages
ansible.builtin.dnf:
name:
- nginx
- certbot
- python3-certbot-nginx
- firewalld
state: present
- name: Start and enable services
ansible.builtin.systemd:
name: "{{ item }}"
state: started
enabled: true
loop:
- nginx
- firewalld
- name: Open firewall ports
ansible.posix.firewalld:
service: "{{ item }}"
permanent: true
immediate: true
state: enabled
loop:
- http
- https
Related Articles
- Handle Yum Failures in Ansible
- Install Packages on Debian/Ubuntu: apt Module
- Ansible Best Practices Guide
- Ansible Privilege Escalation
- Ansible Roles Explained
Conclusion
Use ansible.builtin.dnf for RHEL 8+/Fedora and ansible.builtin.yum for RHEL 7. For cross-platform playbooks, use ansible.builtin.package. Always specify state: present (not latest) unless you intentionally want updates, use update_cache: true for fresh repos, and allow_downgrade: true when pinning specific versions. List multiple packages in a single name array — it's faster than looping individual install tasks.