How to Create a Linux RPM Package

How to Create a Linux RPM Package

If you’ve been using Linux for some time now, you must have heard the term packages and names like RPM packages or DEB packages. You might have also installed some of these packages on your system. Packages are just like software.

In the way we have .exe files in Windows, in the Linux ecosystem we have packages to install.

In this tutorial, we’ll create a RedHat Linux package or RPM package of our own, which is intended for distros such as Fedora, CentOS, Rocky Linux, AlmaLinux, openSUSE, and others. We will write a simple hello world script and create an RPM package for it.

What is a Linux Package?

package is a compressed file or archive that contains all the files with a given application in Linux distributions. The files are normally stored in the package in the order in which they were installed on the system. Most packages additionally include instructions for installing as well as a list of dependencies.

The most popular file extensions of packages are

  • .deb – used by all Debian type Linux
  • .rpm – used by RedHat type Linux
  • .tgz – mainly different TAR Packages (used by Arch Linux and Slackware)

So you can now understand these packages are named by their extensions. Packages can be installed via commands – Debian packages can be installed via the dpkg command, RPM packages can be installed via the rpm command.

Linux packages generally don’t provide the dependencies needed to install them. So different Linux distros use their own package managers for proper installation of the packages.

APT, YUM, Pacman are examples of such package managers. You can easily download, install, update, remove, and do all sorts of things with packages by using these package managers.

There are packages provided by companies, communities, corporations and other contributors from all over the world. Different software developers create packages of their own.

You may be thinking that it would be really amazing if you can create your own package. For example, you have written a mini software script and you want to make it available for everybody to install and use it. To do this, all you have to do is create a package from it and share this package with others to install on their systems.

What is an RPM package?

RPM is a shorthand for Red Hat Package Manager. It was created by Red Hat and is used on Linux operating systems that are based on Red Hat (Fedora, CentOS, RHEL, AlmaLinux, Rocky Linux, openSUSE, etc.).

An RPM package (.rpm) is defined by the .rpm extension. It may include the following:

  • Binary Files (executables) – computer programs that run on a computer (sh, ssh, sshd, and so on)
  • Configuration Files – Different configuration related information of software (sshd.conf, updatedb.conf etc.)
  • Document Files – Required documentation written for the packages (README, Version, AUTHOR, etc.)

The name of an RPM package follows this format:


An example:


First Step To Create An RPM Package

We will now create an RPM of our own. As we are creating an RPM package, we will need an RHEL based distro, like RedHat or CentOS.

We need to install the rpmdevtools package to build the RPM package. We will also install rpmlint to check for errors of our package files.

Command for installing the packages is below:

yum install -y rpmdevtools rpmlint

word image 38

word image 39

After installing rpmdevtools, our package creation process will begin. We usually create an RPM as a non-root user, not root user. So we first switch to a non-root user.

word image 40

Now we first have to create the file tree, which is the directory and configuration directory boilerplate we need to build RPM packages.

In my case, I’m in the non-root user’s (called xyz) home directory and I’ll create the new directory.

To do this run:


word image 41

If we check the contents and list subdirectories recursively with $ ls -R command, we can easily list and see the structure of the rpmbuild directory.

word image 42

Here we can see the different subdirectories under this rpmbuild directory.

Let’s now understand the subdirectories under rpmbuild. The directories are:

  1. rpmbuild/BUILD: This directory is deployed during the RPM package’s build process. This is where temporary files are kept and so on.
  2. rpmbuild/RPMS: This directory contains RPM packages for several architectures and noarch if requested in the .spec file or in the build.
  3. rpmbuild/SOURCES: This directory contains sources of the package. The sources are usually compressed as .tar.gz or .tgz files.
  4. rpmbuild/SPEC: This directory contains the .spec files where it is specified how a package is created and related information.
  5. rpmbuild/SRPMS: In this directory the .src or source RPM packages are located.

Creating the bash script

Now we create a simple bash script which will echo something on the terminal. We will write a .sh file and edit it now using nano.

word image 43

word image 44

Now we write the script and save it. This is just a basic bash script, which will echo Hello World and some other texts in the terminal. To start any .sh or bash script, we write #!/bin/bash at the first line.

We can also run it to check whether it shows the right output or not.

To run a script, we use the sh command. Given below:


word image 45

Now we create a new folder for our package, named myrpm-0.0.1 with 0.0.1 denoting the version of the package we will create. To do this run:

mkdir myrpm-0.0.1

Then we move the .sh script in this directory. To do this run:

mv myrpm-0.0.1

word image 46

Now let us create an archived or zipped folder of it. For this we will use tar and name or tarball as myrpm-0.0.1.tar.gz. To do this run:

tar -cvzf myrpm-0.0.1.tar.gz myrpm-0.0.1

word image 47

Now we move it to the Sources directory and list the contents of the directory via following commands.

mv myrpm-0.0.1.tar.gz rpmbuild/SOURCES
ls -R rpmbuild/

word image 48

.spec file creation

An RPM package is defined and documented by a .spec file.

The command to create a .spec file named as myrpm is:

rpmdev-newspec myrpm

word image 49

Now we move the spec file to /SPECS directory. And then we can check our rpmbuild directory hierarchy how it looks like using tree command.

tree rpmbuild

word image 50

Let us now open the spec file using nano (or your preferred text editor) and check what it contains.

word image 51

word image 52

Our generated .spec file contains a basic boilerplate of some pre-ready information regarding a RPM package.

Let us first understand in brief what a .spec file contains.

Preamble Items:

  1. Name: Name is what the package will be called. It should match the name of the .spec file.
  2. Version: The package version.
  3. Release: The package version number.
  4. Summary: Simple summary of what the package is about.
  5. License: The license of the software or package used.
  6. Source0: Path or URL to the compressed archive file of the source of RPM.
  7. BuildArch: For which architecture the package is built for.
  8. BuildRequires: List of packages or software needed to build the RPM.
  9. Requires: List of packages or software needed to run the RPM after installing.

Body Items:

  1. %description – A simple description of the software packaged in the RPM.
  2. %prep – This section contains the script that will first execute during the build process of the RPM.
  3. %build – This section is for performing the build.
  4. %install – This section is also executed like %prep and %build section and is used for the installation.
  5. %files – This section contains the list of files that the package contains.
  6. %clean – This section instructs the RPM to clean up any files that are not needed after build.
  7. %changelog – A log of changes may happen to the package between different versions and releases.

We will add information in the .spec file as per our own. We will now add in the Name section and Version section, but Name must match the .spec file name.

For Release, here 1%{?dist} means if %{dist} is defined, insert its value here. If not, do nothing.

This dist tag is known as distro or distribution tag. It means which distro is used for this RPM package creation, like if we build an RPM on CentOS 7 we should get it as .el7.

We also add in the Summary section and set the Source0 section as per our tarball in /SOURCES directory. We removed the “BuildArch” and “BuildRequires” sections as we don’t need them for now. We set the “Requires” section as bash because we are ruuning a .sh script for which bash is needed.

After that we added a description and set the %prep section as with another shortcut %setup with -q. We can also leave it as %autosetup.

word image 53

As of now you can see that there are a lot of shortcuts or we can say predefined variables starting with % in .spec files. They’re called macros. RPM provides predefined a lot of macros to make package maintenance simpler. You can get all the information regarding macros in the Fedora official documentation.

For now, the shortcut’s full evaluated form can be found if we run the commands in the terminal. The syntax is:

rpm --eval <macro>

For example, if I want to see what the %{_bindir} contains, we run the command:

rpm --eval '%{_bindir}'

word image 54

Now we change the section with macros on our own and add something on these.

$RPM_BUILD_ROOT or the equivalent %{buildroot} macro holds the directory under which RPM will look for files to package.

In the %install section we first clear the previous directories, then create a new directory with the %{_bindir} macro and finally copy the .sh script to this directory.

Then we clean the directory in the %clean section. In the %file section, we added the .sh script.

And in the %changelog section we’ve just added the release version of the rpm as log.

word image 55

Now our spec is ready. We can check this for any error using rpmlint. The command is:

rpmlint rpmbuild/SPECS/myrpm.spec

word image 56

We get no error, but two warnings. We can ignore the warnings for now.

One is for build section and another one is for invalid url as we haven’t added any build section.

Package creation

There are two types of RPM packages:

  • Source RPM (SRPM) – contains source code and a SPEC file
  • Binary RPM – contains the binaries built from the sources

We first create the source RPM. Command is:

rpmbuild -bs rpmbuild/SPECS/myrpm.spec

Here -b is for build , and -s is for source.

See the man page of rpmbuild for more clarification.

word image 57

We can create the binary RPM using below command:

rpmbuild -bb rpmbuild/SPECS/myrpm.spec

Here -b is for build , and -b is for binary.

We can also create both source and binary together using the command:

rpmbuild -ba rpmbuild/SPECS/myrpm.spec

Here -b is for build , and -a is for all.

word image 58

word image 59

Now our rpm package is ready. Let us again check our rpmbuild directory tree and see what it contains now.

Run the command:

tree rpmbuild

word image 60

Installing the RPM package

To install we can use yum or rpm. Commands are given below:

yum install rpmbuild/RPMS/x86_64/myrpm-0.0.1-1.el8.x86_64.rpm
rpm -ivh rpmbuild/RPMS/x86_64/myrpm-0.0.1-1.el8.x86_64.rpm

Here I have switched to root and using yum I’ve installed my package.

word image 61

word image 62

Our package is installed. To check we can use

rpm -qa myrpm

Here -q is for query, -a is for all.

word image 63

We can also use other options with the rpm command.

rpm -qi myrpm

Here -q is for query, -i is for info.

word image 64

We can also check where our script is listed and located using the following command:

rpm -ql myrpm

Here -q is for query, -l is for list.

word image 65

Removing the RPM package

We can remove packages using yum remove or rpm. The commands are:

yum remove myrpm
rpm -Ve myrpm

Here -V is for verbose, and -e is for erase.

word image 66

word image 67


That’s it. This is the minimalistic process of creating an rpm package of our own, installing it, and finally removing it. If you have any feedback or questions feel free to leave a comment.

Notify of
Receive notifications when your comment receives a reply. (Optional)
Your username will link to your website. (Optional)

Inline Feedbacks
View all comments
You May Also Like