Building RPM packages - Part 1

Sun, 2 Apr. 2023     Thomas Bendler     ~ 4 min to read

Especially in the enterprise application area, I often see software delivered as an archive with its self-developed installation program or script. Although it’s not fundamentally wrong, it’s also not ideal. This is primarily true for smaller, encapsulated software packages. The better way would be to package the software and incorporate the software package into the distributions package manager. This enables centralized software management including dependencies, version control, security information, etc. without additional processes or tools. Indeed, this does not apply to every software package. If you, for example, take SAP S/4 HANA, it’s a software package you can’t pack as RPM because there is way too much additional information required, all exclusively used by SAP. But let’s have a look at the less complex SAP products like the SAP Router. It’s a small standalone application with a dedicated release cycle which is usually installed on a separate machine. Instead of manually maintaining the application, it is a perfect candidate for an RPM package.

But how is it done? Well, first we need to build a structure/ framework for the SAP Router. When you download the SAP Router from the OSS marketplace, you’ll get a SAR file containing a few files and that’s it. It’s up to you to organize the SAP Router operation on your local box. So, the first question is, where do you run your software? As it’s an optional package from a third-party vendor, the most obvious location is underneath /opt/sap. So the first RPM that I build, deploys the basic directory layout for the additional packages I build (like the SAP Router).

But how is it done? First, we need to create our build environment for the RPM build. To achieve this, install the required packages:

sudo dnf -y install rpmdevtools rpm-build redhat-rpm-config rpmlint make gcc gpg

Next, decide which user should be your build user. I use my normal user to build the rpm packages but this can be done differently as well. Login as the build user and create the RPM build directory structure:

mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

Once done, the build configuration file ($HOME/.rpmmacros) needs to be created:

%packager Thomas Bendler
%_topdir /home/thbe/rpmbuild
%_tmppath /home/thbe/rpmbuild/tmp
%_signature gpg
%_gpg_path /home/thbe/.gnupg
%__gpg_sign_cmd %{__gpg} gpg --force-v3-sigs --batch --verbose --no-armor --no-secmem-warning -u "%{_gpg_name}" -sbo %{__signature_filename} --digest-algo sha256 %{__plaintext_filename}'

In principle, you could already start building RPMs but there is one thing missing. As you can see in the configuration file, I have configured the signing of RPM packages. This means, after every successful build, the RPM package is cryptographically signed. This allows the consumer of the package to validate the correct content of the RPM using your public key. This requires two tasks, you need to create a GPG key for the signing process and you need to share your public RPM-GPG key. The first task is done like this:

thbe@spock ~/rpmbuild $ gpg --gen-key
gpg: directory '/home/thbe/.gnupg' created
gpg: keybox '/home/thbe/.gnupg/pubring.kbx' created
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Thomas Bendler
Email address:
You selected this USER-ID:
    "Thomas Bendler <>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
thbe@spock ~/rpmbuild $

Now you need to export the RPM-GPG-KEY:

gpg --export -a '' > rpmbuild/RPM-GPG-KEY-thbe

The key needs to be placed in a publicly accessible location. I, for example, uploaded the RPM key to my website. Now, everyone who would like to use my RPM packages can import the key into his RPM database to verify if the content of the RPM is what I have built:

rpm --import

In the next part of this series, I will demonstrate how to build the first RPM.

Building RPM packages:

Share on: