diff --git a/cdist/conf/type/__package_dnf/explorer/pkg_version b/cdist/conf/type/__package_dnf/explorer/pkg_version
new file mode 100755
index 00000000..9b3df108
--- /dev/null
+++ b/cdist/conf/type/__package_dnf/explorer/pkg_version
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+# Retrieve the status of a package
+#
+
+if [ -f "$__object/parameter/name" ]
+then name="$(cat "$__object/parameter/name")"
+else name="$__object_id"
+fi
+
+rpm -q "$name" 2>/dev/null || rpm -q --whatprovides "$name" 2>/dev/null || true
diff --git a/cdist/conf/type/__package_dnf/gencode-remote b/cdist/conf/type/__package_dnf/gencode-remote
new file mode 100755
index 00000000..c9f217fe
--- /dev/null
+++ b/cdist/conf/type/__package_dnf/gencode-remote
@@ -0,0 +1,70 @@
+#!/bin/sh -e
+#
+# 2024 Romain Dartigues
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see .
+#
+#
+# Manage packages with DNF (Fedora ≥ 18, RHEL ≥ 8, OpenMandriva)
+#
+
+if [ -f "$__object/parameter/name" ]
+then name="$(cat "$__object/parameter/name")"
+else name="$__object_id"
+fi
+
+# Support installing from an URL
+if [ -f "$__object/parameter/url" ]
+then install_name="$(cat "$__object/parameter/url")"
+else install_name="$name"
+fi
+
+
+state_should="$(cat "$__object/parameter/state")"
+
+if grep -q -E "(scientific|centos|redhat|amazon)" "$__global/explorer/os"
+then opts="-y --quiet"
+else opts="--assumeyes --quiet"
+fi
+
+not_provided="^no package provides"
+not_installed='is not installed$'
+
+if grep -q "$not_provided" "$__object/explorer/pkg_version"
+then
+ if grep -q "$not_installed" "$__object/explorer/pkg_version"
+ then state_is="absent"
+ else state_is="present"
+ fi
+else state_is="present"
+fi
+
+[ "$state_is" = "$state_should" ] && exit 0
+
+case "$state_should" in
+ present)
+ echo "dnf $opts install '$install_name'"
+ echo "installed" >> "$__messages_out"
+ ;;
+ absent)
+ echo "dnf $opts remove '$name'"
+ echo "removed" >> "$__messages_out"
+ ;;
+ *)
+ echo "Unknown state: $state_should" >&2
+ exit 1
+ ;;
+esac
diff --git a/cdist/conf/type/__package_dnf/man.rst b/cdist/conf/type/__package_dnf/man.rst
new file mode 100644
index 00000000..1ca1d88c
--- /dev/null
+++ b/cdist/conf/type/__package_dnf/man.rst
@@ -0,0 +1,70 @@
+cdist-type__package_dnf(7)
+==========================
+
+NAME
+----
+cdist-type__package_dnf - Manage packages with dnf
+
+
+DESCRIPTION
+-----------
+:abbr:`dnf (Dandified YUM)` is the next-generation version of the :abbr:`YUM (Yellowdog Updated Manager)`
+used on the Fedora (≥ 18), :abbr:`RHEL (Red Hat Enterprise Linux)` ≥ 8 and derivated, OpenMandriva, …)
+distributions to manage packages.
+
+If ``dnf`` is not available on the platform, it will automatically try to fallback to ``yum``.
+
+
+REQUIRED PARAMETERS
+-------------------
+None
+
+
+OPTIONAL PARAMETERS
+-------------------
+name
+ If supplied, use the name and not the object id as the package name.
+
+state
+ Either "present" or "absent", defaults to "present"
+
+url
+ URL to use for the package
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # Ensure zsh in installed
+ __package_dnf zsh --state present
+
+ # If you don't want to follow pythonX packages, but always use python
+ __package_dnf python --state present --name python3
+
+ # Remove obsolete package
+ __package_dnf puppet --state absent
+
+ __package epel-release \
+ --url https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
+
+
+SEE ALSO
+--------
+:strong:`cdist-type__package`\ (7),
+:strong:`cdist-type__package_yum`\ (7)
+
+
+AUTHORS
+-------
+Romain Dartigues,
+based on Nico Schottelius work on :strong:`cdist-type__package_man`\ (7)
+
+
+COPYING
+-------
+Copyright \(C) 2024 Romain Dartigues. You can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
diff --git a/cdist/conf/type/__package_dnf/nonparallel b/cdist/conf/type/__package_dnf/nonparallel
new file mode 100644
index 00000000..e69de29b
diff --git a/cdist/conf/type/__package_dnf/parameter/default/state b/cdist/conf/type/__package_dnf/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__package_dnf/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__package_dnf/parameter/optional b/cdist/conf/type/__package_dnf/parameter/optional
new file mode 100644
index 00000000..9293119d
--- /dev/null
+++ b/cdist/conf/type/__package_dnf/parameter/optional
@@ -0,0 +1,3 @@
+name
+state
+url