You need one RPM on a server with no internet, and the dependency list is longer than you expected. On modern RPM-based systems that use DNF, dnf download pulls packages from enabled repositories without installing them. Add --resolve and --alldeps, match the download host to your offline target, copy the files, and install with dnf install on the disconnected machine.
This guide walks through that workflow on Fedora and RHEL-compatible distributions (RHEL, Rocky Linux, AlmaLinux, CentOS Stream, Oracle Linux). I ran the examples on Rocky Linux 10.2 with DNF 4.20; repository names and package versions differ by release, and some option names differ between DNF4 and DNF5, but the overall workflow remains the same.
Tested on: Rocky Linux 10.2 (Red Quartz); kernel 6.12.0-211.16.1.el10_2.0.1.x86_64; DNF 4.20.0.
Check Whether You Are Using DNF4 or DNF5
Do not assume the DNF generation from the distribution name alone. The same major release can ship DNF4 by default while DNF5 is available as an optional package, or both binaries may be installed during a migration period. Fedora made DNF5 the default starting with Fedora 41; Rocky Linux 10 still defaults to DNF4 on a fresh install, even though DNF5 can be added separately on some builds.
| System | What to do |
|---|---|
| RHEL-compatible systems | Run dnf --version; many still use DNF4 |
| Fedora 41 and later | DNF5 by default |
| Systems with both installed | Check whether dnf invokes DNF4 or DNF5 |
| Scripts used across distributions | Detect supported flags with dnf download --help |
Check the installed DNF version:
dnf --version4.20.0
Installed: dnf-0:4.20.0-22.el10_2.rocky.0.1.noarch at Mon 06 Jul 2026 03:27:42 PM GMT
Built : Rocky Linux Build System <[email protected]> at Tue 19 May 2026 02:06:23 PM GMT
Installed: rpm-0:4.19.1.1-23.el10.x86_64 at Mon 06 Jul 2026 03:27:40 PM GMTA leading 4.x means DNF4; 5.x means DNF5. On DNF5 hosts the dnf command may be a symlink to dnf5, or you may call dnf5 directly when both binaries are installed.
Confirm download options on your build:
dnf download --help | grep -E 'destdir|downloaddir'[--refresh] [-4] [-6] [--destdir DESTDIR] [--downloadonly]
--destdir DESTDIR, --downloaddir DESTDIROn this Rocky Linux 10 host both names appear because recent DNF4 builds accept --destdir as an alias. On older DNF4 systems you may only see --downloaddir; on DNF5, use --destdir.
DNF4 vs DNF5 download syntax
| Task | DNF4 | DNF5 |
|---|---|---|
| Download one package | dnf download package |
dnf download package |
| Resolve dependencies | --resolve |
--resolve |
| Include installed dependencies | --alldeps |
--alldeps |
| Select destination directory | --downloaddir |
--destdir |
| Restrict architecture | --arch |
--arch (repeat per arch) |
| Disable all remote repos (offline install) | --disablerepo='*' |
--disable-repo='*' |
| Enable an extra repository | --enablerepo=repo |
--enable-repo=repo |
| Install download plugin support | dnf-plugins-core |
download is in the standard command set |
Install dnf-plugins-core on DNF4 systems
dnf download ships in the dnf-plugins-core package on DNF4 systems. Install it when the subcommand is missing:
sudo dnf install -y dnf-plugins-corePackage dnf-plugins-core-4.7.0-10.el10.noarch is already installed.On Rocky Linux 10.2 the package was already present. On a minimal RHEL install you may need to enable standard repositories first.
DNF5 command availability
On DNF5, download is part of the standard command set, not an optional plugin collection. Verify it with:
dnf download --helpWhen the dnf and dnf5 binaries are both installed, you can also run:
dnf5 download --helpDNF5 removed --help-cmd; use -h or --help only. If download is unavailable, check how your distribution packages DNF5 rather than assuming the DNF4 dnf-plugins-core package provides it.
Download an RPM Without Installing It
Start with a package that is not installed locally so you can see the bare download behavior. I used htop from EPEL, which was not on this system.
dnf download normally does not require root when the destination directory and user cache are writable. Root access is required to install dnf-plugins-core, modify system repository configuration, or install the downloaded RPMs later.
DNF4
Create a working directory and download the package only:
mkdir -p ~/rpm-downloadsdnf download --downloaddir ~/rpm-downloads htopLast metadata expiration check: 0:34:58 ago on Fri 10 Jul 2026 09:19:14 AM IST.
htop-3.3.0-5.el10_0.x86_64.rpm 119 kB/s | 196 kB 00:01List what landed in the directory:
ls -1 ~/rpm-downloads/htop-3.3.0-5.el10_0.x86_64.rpmOne RPM file, no dependency packages — sufficient only when the target already has every required dependency at compatible versions. For most offline installs you need --resolve --alldeps.
DNF5
The package name is the same; only the destination flag changes:
mkdir -p ~/rpm-downloadsdnf download --destdir ~/rpm-downloads htopDNF5 uses --destdir instead of --downloaddir. Run dnf download --help on the download host to confirm the option name before you automate.
Download an RPM with All Dependencies
For offline targets, combine --resolve with --alldeps. The difference matters most when the package you want is already installed on the download host.
DNF4
Download htop with the resolved dependency set from the currently enabled repositories:
mkdir -p ~/rpm-downloadsdnf download --resolve --alldeps --downloaddir ~/rpm-downloads htop(1/30): libcap-ng-0.8.4-6.el10.x86_64.rpm 25 kB/s | 32 kB 00:01
(2/30): libcap-2.69-7.el10_1.1.x86_64.rpm 57 kB/s | 85 kB 00:01
...
(30/30): tzdata-2026b-1.el10_2.noarch.rpm 948 kB/s | 497 kB 00:00Thirty RPM files for one monitoring tool — that is normal when --alldeps pulls in libraries from BaseOS, AppStream, and EPEL.
A larger application such as nginx from AppStream can produce a much bigger bundle. On Rocky Linux 10 the same command pulled one hundred eleven RPMs for nginx.
DNF5
Same flags, DNF5 destination syntax:
mkdir -p ~/rpm-downloadsdnf download --resolve --alldeps --destdir ~/rpm-downloads package-nameReplace package-name with the binary you need on the offline host.
Download multiple packages in one resolution
Resolve several applications in one command to avoid duplicate RPM files and confirm the combined transaction is solvable:
dnf download --resolve --alldeps --destdir ~/rpm-downloads htop nginx rsyncDNF deduplicates shared dependencies across the requested packages.
Difference between --resolve and --alldeps
I compared the two flags on vim-minimal, which was already installed on the download host.
With --resolve only:
mkdir -p /tmp/rpm-resolve
dnf download --resolve --destdir /tmp/rpm-resolve vim-minimal(1/2): vim-data-9.1.083-9.el10_2.4.noarch.rpm 16 kB/s | 17 kB 00:01
(2/2): vim-minimal-9.1.083-9.el10_2.4.x86_64.rp 346 kB/s | 798 kB 00:02Two RPMs — DNF skipped libraries already present on the download system.
With --resolve --alldeps:
mkdir -p /tmp/rpm-alldeps
dnf download --resolve --alldeps --destdir /tmp/rpm-alldeps vim-minimal(1/23): vim-data-9.1.083-9.el10_2.4.noarch.rpm 19 kB/s | 17 kB 00:00
...
(23/23): pcre2-syntax-10.44-1.el10.3.noarch.rpm 120 kB/s | 150 kB 00:01Twenty-three RPMs — the resolved dependency set for that repository and release state, including packages DNF considered satisfied locally.
| Command | Behaviour | Suitable for offline target? |
|---|---|---|
dnf download package |
Downloads only the requested package | Usually no |
dnf download --resolve package |
Downloads dependencies not already satisfied locally | Sometimes |
dnf download --resolve --alldeps package |
Downloads the package and the complete dependency set resolved from enabled repositories | Usually yes |
--alldeps means DNF does not skip dependencies merely because they are already installed locally. The set is still calculated from enabled repositories, available versions, architecture, solver configuration, and repository metadata on the download host. It cannot compensate for a target locked to an older minor release, missing vendor repositories, different package exclusions, or multilib requirements.
--alldeps resolves dependencies using the repositories and metadata on the download system. It cannot fix a wrong OS release, missing EPEL, or an architecture mismatch on the offline target.
Optional: exclude weak dependencies
Some bundles grow large because repository metadata includes weak dependencies such as recommendations. To download required dependencies but skip recommended packages:
dnf --setopt=install_weak_deps=False download --resolve --alldeps --destdir ~/rpm-downloads package-nameUse this only when you intentionally want a smaller bundle. The resulting application may lack optional functionality.
Prepare Packages for Another Offline System
The download host and the offline target should look alike. Run the checks in the table on both machines before you copy anything.
| Item | Command | Why it matters |
|---|---|---|
| Distribution and release | cat /etc/os-release |
Packages should match the target distribution and major release |
| Architecture | uname -m |
Prevents downloading incompatible RPM architectures |
| Enabled repositories | dnf repolist |
Dependencies may come from BaseOS, AppStream, CRB, EPEL, or vendor repos |
| Available package versions | dnf list --showduplicates package-name |
Helps select the correct version |
| Package repository | dnf repoquery --info package-name |
Shows where the package comes from |
| DNF version | dnf --version |
Determines whether DNF4 or DNF5 syntax applies |
On the download host:
cat /etc/os-release | grep -E '^(NAME|VERSION_ID)='NAME="Rocky Linux"
VERSION_ID="10.2"uname -mx86_64dnf repolistrepo id repo name
appstream Rocky Linux 10 - AppStream
baseos Rocky Linux 10 - BaseOS
epel Extra Packages for Enterprise Linux 10 - x86_64
extras Rocky Linux 10 - ExtrasMatch distribution, release, and repository state
Download Rocky Linux 9 RPMs on a Rocky Linux 9 host for a Rocky Linux 9 offline server. A Rocky Linux 10 download host produces packages that will not satisfy dependencies on Rocky Linux 9, even when the package name is identical.
Matching the major version is the minimum requirement. If the target is pinned to a minor release, RHEL EUS channel, repository snapshot, or version lock, prepare the bundle against the same repository state. A bundle downloaded from the latest Rocky Linux 9 repositories may conflict with a server intentionally held at an earlier Rocky Linux 9 package level. DNF supports overriding releasever, including major and minor components, when you need to align with a pinned target.
Compare uname -m on both systems. Download x86_64 RPMs for an x86_64 target. Include noarch packages in the bundle; they install on any supported architecture.
EPEL, CRB, and third-party repositories
If the target needs a package from EPEL, enable EPEL on the download host before you run dnf download. The same applies to CRB (CodeReady Builder) on RHEL-compatible systems when a dependency lives there.
See which repository provides a package:
dnf repoquery --info htopName : htop
Version : 3.3.0
Release : 5.el10_0
Architecture : x86_64
Repository : epel
Summary : Interactive process viewerhtop comes from EPEL on this host, so EPEL must stay enabled during the download. Every EPEL RPM needed by the package must be in your copied directory even when the offline target does not use EPEL for online installs.
Select a Version, Architecture, or Repository
Exact package version (NEVRA)
List available builds, then pin the version you want:
dnf list --showduplicates htopAvailable Packages
htop.x86_64 3.3.0-5.el10_0 epelname-version-release usually works. A full NEVRA is the least ambiguous format when multiple architectures or epochs exist:
dnf download --resolve --alldeps --destdir ~/rpm-downloads htop-0:3.3.0-5.el10_0.x86_64DNF downloads that exact build and its resolved dependency tree.
x86_64 and noarch only
On DNF4 you can pass a comma-separated architecture list:
dnf download --resolve --alldeps --arch=x86_64,noarch --downloaddir ~/rpm-downloads htopOn DNF5 repeat --arch for each architecture:
dnf download --resolve --alldeps --arch=x86_64 --arch=noarch --destdir ~/rpm-downloads package-nameDo not automatically exclude i686 unless you are certain the target never needs multilib libraries. Some applications still pull 32-bit dependencies.
Repository selection: --enable-repo, --repo, and --from-repo
These options behave differently. Pick the one that matches what you are trying to restrict.
| Option | DNF4 name | DNF5 name | Effect |
|---|---|---|---|
| Enable an additional repository | --enablerepo=epel |
--enable-repo=epel |
Enables EPEL but does not restrict where the requested package comes from |
| Restrict the entire transaction | --repo=epel |
--repo=epel |
Only EPEL is used; dependencies must also exist in that repository |
| Restrict the requested package only | (not available) | --from-repo=epel |
htop must come from EPEL; dependencies may resolve from other enabled repositories |
On DNF4, --repo=epel restricts the entire transaction and fails when dependencies live in BaseOS or AppStream:
dnf download --resolve --alldeps --repo=epel --destdir /tmp/epel-only htopError:
Problem: conflicting requests
- nothing provides libhwloc.so.15()(64bit) needed by htop-3.3.0-5.el10_0.x86_64 from epel--enablerepo=epel only ensures EPEL is enabled; it does not guarantee the requested package is selected from EPEL when the same name exists elsewhere.
On DNF5, download the requested package from EPEL while resolving dependencies from all enabled repositories:
dnf download --resolve --alldeps --from-repo=epel --destdir ~/rpm-downloads htopTransfer, Verify, and Install the Bundle Offline
Prefer dnf install over rpm -ivh so DNF orders the transaction and reports missing dependencies clearly. See RPM dependency errors when a manual rpm install fails.
Create and transfer the bundle
Copy the directory with rsync, scp, USB media, or an archive:
rsync -av ~/rpm-downloads/ offline-host:/tmp/offline-rpms/Keep the RPM files in one directory on the target.
Verify package signatures and checksums
Check RPM signatures on the download host before transfer:
rpmkeys --checksig ~/rpm-downloads/*.rpm/home/user/rpm-downloads/htop-3.3.0-5.el10_0.x86_64.rpm: digests signatures OKrpm -K is the shorter compatibility form and produces equivalent verification output on the tested system.
digests signatures OK means the RPM checksum and signature verified against imported GPG keys. If the output contains NOKEY, the digest may be intact, but the package signing identity has not been verified because the required repository key is not imported. Import the trusted distribution or repository signing keys on the offline target. Obtain the keys from verified installation media, an installed release package, or another trusted source rather than treating a key copied alongside the RPM bundle as independently trustworthy.
Create a checksum manifest when copying by USB, file share, or multi-hop transfer:
cd ~/rpm-downloads
sha256sum *.rpm > SHA256SUMSVerify on the offline system after copy:
cd /tmp/offline-rpms
sha256sum -c SHA256SUMSVerify the RPM signatures again on the offline target:
rpmkeys --checksig /tmp/offline-rpms/*.rpmDo not assume that dnf install /path/*.rpm always verifies signatures for local files. The localpkg_gpgcheck setting is disabled by default in upstream DNF4 and DNF5, although a distribution may override it.
To require DNF to verify local package signatures for this transaction on DNF4:
sudo dnf --setopt=localpkg_gpgcheck=True --disablerepo='*' install /tmp/offline-rpms/*.rpmOn DNF5, use --disable-repo='*' instead of --disablerepo='*'.
rpmkeys --checksig verifies package digests and signatures, but it needs the appropriate trusted public key to verify package origin.
List package names, versions, and architectures:
rpm -qp --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' ~/rpm-downloads/*.rpmhtop-3.3.0-5.el10_0.x86_64
libcap-2.69-7.el10_1.1.x86_64
...Test the transaction
Dry-run the offline install on a machine that matches the target (a clean VM is ideal):
sudo dnf --disablerepo='*' install --assumeno ~/rpm-downloads/*.rpmIf the transaction completes without errors in the dry run, the bundle is likely complete. On my live Rocky Linux 10 host, testing a full --alldeps tree that included newer glibc builds produced version conflicts with packages already installed — that is why you should validate on a clean VM matching the offline target, not only on the download host.
Simulate a missing dependency by installing a single RPM from the bundle:
sudo dnf --disablerepo='*' install --assumeno /tmp/rpm-test-missing/htop-3.3.0-5.el10_0.x86_64.rpmError:
Problem: conflicting requests
- nothing provides libhwloc.so.15()(64bit) needed by htop-3.3.0-5.el10_0.x86_64 from @commandlineRe-run the download with --resolve --alldeps and every required repository enabled before you rely on the bundle.
Install without remote repositories
Providing local RPM paths does not automatically disable configured repositories; DNF may still refresh metadata or search repositories unless they are explicitly disabled.
If the target still has repository access, a simple local install works:
sudo dnf install /tmp/offline-rpms/*.rpmOn a fully disconnected host, disable every remote repository so DNF uses only the files you copied.
DNF4:
sudo dnf --disablerepo='*' install /tmp/offline-rpms/*.rpmDNF5:
sudo dnf --disable-repo='*' install /tmp/offline-rpms/*.rpmEvery dependency must already be in /tmp/offline-rpms/. If anything is missing, DNF stops with a nothing provides error instead of fetching from the network.
Common Errors and Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
nothing provides lib… on offline install |
Incomplete bundle; --alldeps omitted or repo disabled during download |
Re-download with --resolve --alldeps; enable EPEL/CRB on the download host |
| Few RPMs downloaded for an installed package | Used --resolve without --alldeps |
Add --alldeps when preparing for another machine |
No such command: download |
dnf-plugins-core not installed (DNF4) |
sudo dnf install dnf-plugins-core |
Unknown argument --downloaddir |
DNF5 host | Use --destdir instead |
digests OK but NOKEY in rpm -K |
Repository GPG key not imported | Import the repo signing key on the download or offline host |
Version conflict with installed glibc or systemd |
Bundle built from newer repos than the pinned target | Match minor release, EUS channel, or snapshot; test on a clean VM |
Error downloading packages / 404 from mirror |
Stale metadata or bad mirror | sudo dnf clean all then retry |
| Fedora RPMs fail on Rocky Linux | Cross-distribution binary mismatch | Re-download on the same distro and major release as the target |
rpm -ivh dependency loop |
Manual install order | Use dnf install *.rpm instead; see dependency list tools |
| Download works as root but not as user | Destination or cache not writable | Fix directory permissions or use a writable ~/rpm-downloads path |
dnf download vs reposync
| Goal | Tool |
|---|---|
| One application and its dependency tree | dnf download --resolve --alldeps |
| Mirror a whole repository for many future installs | dnf reposync |
| Long-term disconnected site with ongoing updates | Local mirror with reposync + createrepo |
dnf download answers “I need this package and everything it needs right now.” reposync answers “I need a copy of everything in BaseOS or EPEL for the next six months.” reposync is provided by dnf-plugins-core on DNF4 systems. On DNF5 systems, install the distribution's DNF5 reposync plugin package when the command is unavailable; Fedora provides it through dnf5-plugins. See download an entire repository for offline use for the mirroring workflow.
Legacy CentOS 7 and RHEL 7 Commands
CentOS 7 and RHEL 7 used YUM instead of DNF. The old tools still appear in search results:
sudo yum install yum-utils
yumdownloader --resolve package-name
repotrack package-nameyumdownloader and repotrack belong to YUM-based systems. On any host running DNF today, use:
dnf download --resolve --alldeps package-nameModern RHEL-compatible releases (8, 9, 10) and current Fedora releases should use the DNF workflow in this article.
Summary
dnf download --resolve --alldeps is the modern replacement for yumdownloader and repotrack. Run dnf --version and dnf download --help on each host rather than assuming DNF4 or DNF5 from the distribution name. Use DNF4's --downloaddir and --disablerepo, or DNF5's --destdir and --disable-repo, match your download host to the offline target's distribution, release, and repository state, then copy and verify the bundle before installing.
Match the target's major release at minimum; align minor releases, EUS channels, and repository snapshots when the production server is pinned. Enable every repository the package needs, verify signatures and checksums, dry-run with --assumeno on a clean VM, and prefer dnf install over rpm -ivh when dependencies are missing. For ongoing offline maintenance at scale, plan a reposync mirror rather than repeated one-off downloads.
For broader DNF command reference and repository troubleshooting on disconnected RHEL nodes, see configure a local offline repository.

