Skip to main content
The dnf module manages packages and repositories on Fedora and RHEL 8+ systems using the dnf package manager.
Dnf package names are case-sensitive.

Functions

packages

Install, remove, or update dnf packages.
from pyinfra.operations import dnf

dnf.packages(
    name="Install web server",
    packages=["nginx", "certbot"],
    update=True,
)
packages
str | list[str]
List of packages to ensure.
present
bool
default:true
Whether the packages should be installed.
latest
bool
default:false
Whether to upgrade packages without a specified version.
update
bool
default:false
Run dnf update before installing packages.
clean
bool
default:false
Run dnf clean before installing packages.
nobest
bool
default:false
Add the —nobest option to install.
extra_install_args
str
Additional arguments to the dnf install command.
extra_uninstall_args
str
Additional arguments to the dnf uninstall command.
Package versions can be pinned as: <pkg>=<version>

Examples

from pyinfra.operations import dnf

# Update package list and install packages
dnf.packages(
    name="Install Vim and Vim enhanced",
    packages=["vim-enhanced", "vim"],
    update=True,
)

update

Update all dnf packages.
from pyinfra.operations import dnf

dnf.update(
    name="Update all packages",
)
This operation is not idempotent - it will always execute.

repo

Add, remove, or update dnf repositories.
from pyinfra.operations import dnf

dnf.repo(
    name="Add Docker repository",
    src="DockerCE",
    baseurl="https://download.docker.com/linux/centos/7/$basearch/stable",
)
src
str
required
URL or name for the .repo file.
present
bool
default:true
Whether the .repo file should be present.
baseurl
str
The baseurl of the repo (if src is not a URL).
description
str
Optional verbose description.
enabled
bool
default:true
Whether this repo is enabled.
gpgcheck
bool
default:true
Whether to set gpgcheck=1.
gpgkey
str
The URL to the GPG key for this repo.
baseurl, description, gpgcheck, and gpgkey are only valid when src is a filename (not a URL). Use a URL to download and install remote repository files.

Examples

from pyinfra.operations import dnf

# Download a repository file
dnf.repo(
    name="Install Docker-CE repo via URL",
    src="https://download.docker.com/linux/centos/docker-ce.repo",
)

rpm

Install or remove .rpm package files.
from pyinfra import host
from pyinfra.operations import dnf
from pyinfra.facts.server import LinuxDistribution

major_centos_version = host.get_fact(LinuxDistribution)["major"]
dnf.rpm(
    name="Install EPEL rpm to enable EPEL repo",
    src=f"https://dl.fedoraproject.org/pub/epel/epel-release-latest-{major_centos_version}.noarch.rpm",
)
src
str
required
Filename or URL of the .rpm package.
present
bool
default:true
Whether the package should exist on the system.
URL sources with present=False: If the .rpm file isn’t downloaded, pyinfra can’t remove any existing package as the file won’t exist until mid-deploy.

key

Add dnf GPG keys with rpm.
from pyinfra import host
from pyinfra.operations import dnf
from pyinfra.facts.server import LinuxDistribution

linux_id = host.get_fact(LinuxDistribution)["release_meta"].get("ID")
dnf.key(
    name="Add the Docker gpg key",
    src=f"https://download.docker.com/linux/{linux_id}/gpg",
)
src
str
required
Filename or URL of the GPG key.
This operation is not idempotent - it always returns one command without state checking.

Common Use Cases

Install EPEL Repository

from pyinfra import host
from pyinfra.operations import dnf
from pyinfra.facts.server import LinuxDistribution

# Get the major version
major_version = host.get_fact(LinuxDistribution)["major"]

# Install EPEL release package
dnf.rpm(
    name="Install EPEL repository",
    src=f"https://dl.fedoraproject.org/pub/epel/epel-release-latest-{major_version}.noarch.rpm",
)

# Install packages from EPEL
dnf.packages(
    name="Install packages from EPEL",
    packages=["htop", "ncdu"],
)

Install Docker on Fedora

from pyinfra import host
from pyinfra.operations import dnf
from pyinfra.facts.server import LinuxDistribution

linux_id = host.get_fact(LinuxDistribution)["release_meta"].get("ID")

# Add Docker GPG key
dnf.key(
    name="Add Docker GPG key",
    src=f"https://download.docker.com/linux/{linux_id}/gpg",
)

# Add Docker repository
dnf.repo(
    name="Add Docker repository",
    src="https://download.docker.com/linux/fedora/docker-ce.repo",
)

# Install Docker
dnf.packages(
    name="Install Docker",
    packages=["docker-ce", "docker-ce-cli", "containerd.io"],
)

System Upgrade

from pyinfra.operations import dnf

# Clean metadata
dnf.packages(
    name="Clean dnf cache",
    packages=[],
    clean=True,
)

# Update all packages
dnf.update(
    name="Update all packages",
)

Development Environment

from pyinfra.operations import dnf

# Install development tools
dnf.packages(
    name="Install Development Tools group",
    packages=["@development-tools"],
)

# Install additional tools
dnf.packages(
    name="Install development utilities",
    packages=[
        "git",
        "vim",
        "tmux",
        "wget",
        "curl",
    ],
    update=True,
)

Build docs developers (and LLMs) love