Offline package installs: downloadonly + a local repo (Rocky 9, tested)
When to use it
Section titled “When to use it”An internal host cannot reach the internet but needs a few packages (or upgrades). Do not scp individual rpms around: download the packages and their dependencies on a connected host, turn the directory into a local repository, and let dnf install from it — dependency resolution and version checks still apply.
Prepare: install createrepo_c first, then download
Section titled “Prepare: install createrepo_c first, then download”dnf -y install createrepo_cmkdir -p /srv/offlinednf -y install --downloadonly --destdir=/srv/offline treels /srv/offlinetree-1.8.0-10.el9.aarch64.rpmOrder matters: install createrepo_c first, then --downloadonly. If you do it the other way round, the next package transaction makes dnf clean the files it just downloaded into the destdir (observed: /srv/offline keeps only repodata and the rpm disappears).
Build the local repository
Section titled “Build the local repository”createrepo_c /srv/offlinels /srv/offline/repodata | head -31cb61ea9...-primary.xml.gz84823fd3...-other.sqlite.bz295a4415d...-filelists.xml.gzrepodata/ is what dnf reads; without it a directory full of rpms is not a repository.
Point dnf at the directory
Section titled “Point dnf at the directory”printf '[local-offline]\nname=Local offline repo\nbaseurl=file:///srv/offline\nenabled=1\ngpgcheck=0\n' \ | sudo tee /etc/yum.repos.d/local.reposudo dnf clean allsudo dnf -y --disablerepo="*" --enablerepo=local-offline install treeInstalled: tree-1.8.0-10.el9.aarch64Complete!--disablerepo="*" is the key: on an isolated host every other repo is unreachable, and leaving them enabled means waiting for timeouts.
Verify
Section titled “Verify”rpm -q treednf --disablerepo="*" --enablerepo=local-offline list availableThe first command prints tree-1.8.0-10.el9.aarch64; the second lists only packages in the local repo.
Common traps
Section titled “Common traps”- Download first, install something else second: the destdir gets cleaned (observed here); always install the tooling first;
- Copy rpms without repodata: dnf cannot see the directory and reports
No match for argument; gpgcheck=0: common for offline repos, but it drops signature verification; carry Rocky’s GPG key and keepgpgcheck=1withgpgkey=file:///...in production.
Practice: install a package with dependencies offline
Section titled “Practice: install a package with dependencies offline”Prerequisite: connected host A and isolated host B, both Rocky 9 (same arch).
# Adnf -y install --downloadonly --destdir=/srv/offline nginxcreaterepo_c /srv/offlinetar -C /srv -czf offline.tgz offline# Bsudo tar -C /srv -xzf offline.tgz# point local.repo at /srv/offline, then:sudo dnf --disablerepo="*" --enablerepo=local-offline install nginxChecks:
rpm -q nginx→ prints a versiondnf --disablerepo="*" --enablerepo=local-offline repoquery --requires nginx | head→ dependencies satisfiedsystemctl is-active nginx→active(needs real systemd; not available in the container)
Next steps
Section titled “Next steps”- Repositories and what is enabled by default: Rocky repositories
- Conflicting repos (page pending):
/en/repo-priority/ - Rolling back: dnf history undo