1. Overview

Red Hat Enterprise Linux, or simply RHEL, is an enterprise-grade OS.

Basically, RHEL 8 comes with two main repositories – BaseOS and AppStream. However, we sometimes need to add an extra repository in an RHEL system. Primarily, there are two reasons for this:

  • the basic repository that comes by default does not contain the required software
  • the default repository contains an outdated version of a software

In this tutorial, we’ll see how to setup a base package repository in RHEL. Specifically, we’ll use an RHEL 8 system for demonstration purposes. However, most of the steps will be identical for other RHEL variants.

2. Enable EPEL Repository on RHEL

Extra Packages for Enterprise Linux, or simply EPEL, is one of the widely used repositories that provides standard additional packages for Enterprise Linux. Fundamentally, the packages provided by EPEL share the same infrastructure as that of Fedora.

Now, let’s check the available repositories installed on our system:

$ dnf repolist
repo id                        repo name
ansible-2-for-rhel-8-rhui-rpms Red Hat Ansible Engine 2 for RHEL 8 (RPMs) from RHUI
rhel-8-appstream-rhui-rpms     Red Hat Enterprise Linux 8 for x86_64 - AppStream from RHUI (RPMs)
rhel-8-baseos-rhui-rpms        Red Hat Enterprise Linux 8 for x86_64 - BaseOS from RHUI (RPMs)
rhui-client-config-server-8    RHUI Client Configuration Server 8

To clarify, on RHEL 8, YUM is a symlink to DNF.

To be sure, we first update the available package on our system for installing the EPEL repository:

$ sudo dnf update

Finally, we can run install the EPEL repository:

$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

The EPEL repository is now installed on our system. Let’s refresh our repository list:

$ dnf repolist
repo id                        repo name
ansible-2-for-rhel-8-rhui-rpms Red Hat Ansible Engine 2 for RHEL 8 (RPMs) from RHUI
epel                           Extra Packages for Enterprise Linux 8 - x86_64
epel-modular                   Extra Packages for Enterprise Linux Modular 8 - x86_64
rhel-8-appstream-rhui-rpms     Red Hat Enterprise Linux 8 for x86_64 - AppStream from RHUI (RPMs)
rhel-8-baseos-rhui-rpms        Red Hat Enterprise Linux 8 for x86_64 - BaseOS from RHUI (RPMs)
rhui-client-config-server-8    RHUI Client Configuration Server 8

We can see the EPEL and its derivative repository are now on our repository list.

2.1. Installing a Package Using EPEL Repository

Now that we’ve set up our EPEL repository, it’s time to use it for installing a package. Let’s install the hping3 package from this repo:

$ sudo dnf --enablerepo=epel install hping3
================================================================================
 Package      Arch     Version                  Repository                 Size
================================================================================
Installing:
 hping3       x86_64   0.0.20051105-33.el8      epel                      105 k
Installing dependencies:
 libibverbs   x86_64   37.2-1.el8               rhel-8-baseos-rhui-rpms   385 k
 libpcap      x86_64   14:1.9.1-5.el8           rhel-8-baseos-rhui-rpms   169 k
 tcl          x86_64   1:8.6.8-2.el8            rhel-8-baseos-rhui-rpms   1.1 M
Transaction Summary
================================================================================
Install  4 Packages
Total download size: 1.8 M
Installed size: 5.7 M
Is this ok [y/N]:

Here we can see the installation wizard is using the EPEL repository for installing the hping**3 package. Besides this, we can also see different dependencies from the RHEL default repository.

3. Manually Creating a Base Repository

Let’s now create a YUM repository manually. In this method, we’ll create a local repository that will host a few packages.

First, let’s create a directory to keep all our demonstration packages:

$ mkdir demo

In this directory, we’ll put some .rpm packages. In general, we can also copy several packages from an RHEL DVD. However, for this article, we’ll use the bind-utils, iproute, and telnet packages:

$ ls demo/
bind-utils-9.11.26-4.el8_4.x86_64.rpm
iproute-5.15.0-4.el8.x86_64.rpm        telnet-0.17-76.el8.ppc64le.rpm

Again, these packages are for demonstration purposes only.

We now need a tool called createrepo for creating a repository. The createrepo command scans a directory containing rpm packages.

In case we don’t have createrepo package already installed, we can install it:

$ sudo dnf install createrepo
================================================================================
Package             Arch     Version        Repository                    Size
================================================================================
Installing:
createrepo_c        x86_64   0.17.7-5.el8   rhel-8-appstream-rhui-rpms    89 k
Installing dependencies:
createrepo_c-libs   x86_64   0.17.7-5.el8   rhel-8-appstream-rhui-rpms   116 k
drpm                x86_64   0.4.1-3.el8    rhel-8-appstream-rhui-rpms    68 k
Transaction Summary
================================================================================
Install  3 Packages
Total download size: 274 k
Installed size: 580 k
Is this ok [y/N]: y

After installing createrepo, we need to pass our demo directory as an argument to the createrepo command:

$ createrepo demo/
Directory walk started
Directory walk done - 3 packages
Temporary output repo path: demo/.repodata/
Preparing sqlite DBs
Pool started (with 5 workers)
Pool finished

Subsequently, after running the above command, we get a new directory called repodata inside of our demo directory.

Now let’s create a repo file in the /etc/yum.repos.d/ directory with the .repo extension:

$ cd /etc/yum.repos.d/
$ sudo vi test.repo

Now, we add the following contents and save the file:

[testrepo]
name=My Test Repo
baseurl=file:///home/ec2-user/demo/
enabled=1
gpgcheck=0

In the next section, we’ll discuss what these parameters basically mean. We’ll now refresh our repository list to see if our testrepo appears in the repository list:

$ sudo dnf repolist
repo id                        repo name
ansible-2-for-rhel-8-rhui-rpms Red Hat Ansible Engine 2 for RHEL 8 (RPMs) from RHUI
rhel-8-appstream-rhui-rpms     Red Hat Enterprise Linux 8 for x86_64 - AppStream from RHUI (RPMs)
rhel-8-baseos-rhui-rpms        Red Hat Enterprise Linux 8 for x86_64 - BaseOS from RHUI (RPMs)
rhui-client-config-server-8    RHUI Client Configuration Server 8
testrepo                       My Test Repo

Consequently, we can see our testrepo listed in the above list.

3.1. Understanding Repository Configuration Files (*.repo)

Let’s explore the lines we added to our testrepo file. The first three lines below the repository ID section are essential. These are the minimum ones required for creating a repo file.

The line [testrepo] is a unique identifier that identifies a repo.

The second line represents the name of our repository. Here the name of this repo file is My Test Repo.

The baseurl line shows the location of the repository. In some cases, like the EPEL repo above, we see a metalink entry and baseurl as commented. This is because metalinks save a user from using malicious mirrors.

The enabled entry has a value of either 0 or 1. In general, enabled=1 means the repo is enabled/active, and 0 here means it’s not enabled/inactive.

These lines are essential for configuring a repository.

Besides these, we have a few more options to configure this file. For instance, we can configure the GPG block. A GPG can be used as a means to sign or verify packages. This way, we can detect and keep off unreliable packages.

Just like the case of enabled, gpgcheck=1  means that it’s enabled, and 0 implies it’s disabled.

3.2. Installing  a Package Using Custom Repository

Next, we’ll use our testrepo repository to install the package iproute:

$ sudo yum --disablerepo="*" --enablerepo="testrepo" install iproute
================================================================================
 Package          Architecture    Version               Repository         Size
================================================================================
Installing:
 iproute          x86_64          5.15.0-4.el8          testrepo          798 k
Transaction Summary
================================================================================
Install  1 Package
Total size: 798 k
Installed size: 2.3 M
Is this ok [y/N]:

Clearly, we can see under the Repository column we’re getting testrepo as the base repository for this installation.

4. Checking a Package Inside a Repository

Now that we’ve created our custom repository, let’s check for the package available to install from here:

$ sudo yum --disablerepo="*" --enablerepo="testrepo" list available
Available Packages
bind-utils.x86_64                  32:9.11.26-4.el8_4                   testrepo
telnet.ppc64le                     1:0.17-76.el8                        testrepo

The –disablerepo option disables all the repositories except for that mentioned by the –enablerepo option. In this list, we can see all the packages available for installation. Equivalently, we can also use the repoquery command:

$ sudo repoquery --disablerepo="*" --enablerepo="testrepo" -i telnet
Name         : telnet
Epoch        : 1
Version      : 0.17
Release      : 76.el8
Architecture : ppc64le
Size         : 76 k
Source       : telnet-0.17-76.el8.src.rpm
Repository   : testrepo

The last row suggests that the repoquery command is scanning our testrepo for querying the telnet package.

5. Conclusion

In this article, we saw how to set up a base repository in RHEL. We used a third-party repository, EPEL, for this purpose. Similarly, we also created a custom repository. Also, we learned how to use a specific repository for installing a package.