Chapter 13: Software management
Repositories and package signatures
dnf can only install what a repository offers, and it trusts a repository to the extent that you tell it to. A repository is a place (a web server, a directory) that holds packages together with a catalogue describing them. This lesson shows how repositories are defined, how package signatures keep them honest, and how to build a small repository of your own, which is a common need for isolated systems.
- Read a
.repofile and explainbaseurl,enabled,gpgcheckandgpgkey. - List, enable and disable repositories, and use a single repository for one command.
- Create a local repository with
dnf downloadandcreaterepo_c, and install from it.
Where repositories are defined
Each file in /etc/yum.repos.d/ ending in .repo can define one or more repositories:
[root@servera ~]# ls /etc/yum.repos.d
rocky-addons.repo rocky-devel.repo rocky-extras.repo rocky-security.repo rocky.repo
[root@servera ~]# dnf repolist
repo id repo name
appstream Rocky Linux 9 - AppStream
baseos Rocky Linux 9 - BaseOS
extras Rocky Linux 9 - Extras
[root@servera ~]# dnf repolist --all | head -4
repo id repo name status
appstream Rocky Linux 9 - AppStream enabled
appstream-debuginfo Rocky Linux 9 - AppStream - Debug disabled
appstream-source Rocky Linux 9 - AppStream - Source disabledRHEL's own software is split in two main repositories: BaseOS (the core operating system) and AppStream (applications, languages and databases, some available in several versions: next lesson). The names you see in your lab depend on the distribution. The shape of the files is the same everywhere:
A repository file: Select a line of a .repo file.
Signatures: why gpgcheck matters
Anyone who can change a repository can change its packages. Each package is therefore signed by its publisher, and gpgcheck=1 makes dnf verify the signature before installing. The public key that verifies it lives in /etc/pki/rpm-gpg/ and is imported into the RPM database as a gpg-pubkey entry:
[root@servera ~]# grep -h gpgkey /etc/yum.repos.d/*.repo | sort -u | head -2
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
[root@servera ~]# rpm -qa 'gpg-pubkey*'
gpg-pubkey-350d275d-6279464brpm -K package.rpm verifies a file you already hold. If you must trust a new vendor, import their key yourself, after checking its fingerprint through a separate channel: rpm --import URL-or-file.
Using one repository, or more
[root@servera ~]# dnf --enablerepo=crb repolist # enable for this command
[root@servera ~]# dnf --disablerepo='*' --enablerepo=baseos list available | head -3To change the default permanently, set enabled=0/1 in the .repo file (or use dnf config-manager --set-enabled ID, from the dnf-plugins-core package). --disablerepo='*' --enablerepo=ID is also the way to prove which repository a package comes from.
Build a local repository
When machines cannot reach a vendor mirror, or you want a fixed, reviewed set of packages, you can serve your own. The recipe has four steps:
Build a repository of your own: Step through creating a local repository from downloaded packages.
First the tools (the download command and the metadata builder):
[root@servera ~]# dnf install -y dnf-plugins-core createrepo_cThen download the packages, with their dependencies, and build the catalogue:
[root@servera ~]# mkdir -p /srv/localrepo
[root@servera ~]# dnf download --resolve --destdir /srv/localrepo zip
(1/2): zip-3.0-35.el9.x86_64.rpm 1.2 MB/s | 263 kB 00:00
(2/2): unzip-6.0-60.el9_8.x86_64.rpm 778 kB/s | 180 kB 00:00
[root@servera ~]# createrepo_c /srv/localrepo
Directory walk started
Directory walk done - 2 packages
Preparing sqlite DBs
Pool started (with 5 workers)
Pool finished
[root@servera ~]# ls /srv/localrepo
repodata unzip-6.0-60.el9_8.x86_64.rpm zip-3.0-35.el9.x86_64.rpmNow describe it. Because these packages are signed by the distribution, keep gpgcheck=1 and point gpgkey at the same key the other repositories use (copy the path from the grep above):
[root@servera ~]# cat > /etc/yum.repos.d/local.repo <<'EOT'
[localrepo]
name=Local repository
baseurl=file:///srv/localrepo
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
EOT
[root@servera ~]# dnf clean all > /dev/null
[root@servera ~]# dnf --disablerepo='*' --enablerepo=localrepo list available
Available Packages
unzip.x86_64 6.0-60.el9_8 localrepo
zip.x86_64 3.0-35.el9 localrepoFinally install from it only, and check where the package came from:
[root@servera ~]# dnf --disablerepo='*' --enablerepo=localrepo install -y zip
...output omitted...
Complete!
[root@servera ~]# dnf info zip | grep 'From repo'
From repo : localrepoA web server can serve the same directory to many machines (baseurl=http://host/repo); chapter 19 offers another way, over NFS.
Try it
Check your understanding
- Where do repository definitions live?
- What does gpgcheck=1 do?
- Which command builds the metadata for a directory of .rpm files?
- How do you use one repository only, for one command?
- What does baseurl=file:///srv/localrepo mean?
- Why not set gpgcheck=0 for convenience?