Learn To Build Your Own RPM On CentOS/RHEL 6/7

Linux is a fascinating OS technology because everything in Linux is a file. You must have heard of RPM (RedHat Package Manager), it’s a package management system for RedHat based operating system like CentOS. In RHEL/CentOS, it is possible to create your installation rpm file. Let’s say we have a code which creates a database dump of a specific database.


Host OS: CentOS/RHEL 6/7
Host IP:
RAM: 4GB memory
Home Dir: /root/


You should have your own code/scripts pre-ready for which we are creating your own rpm.

Let’s start

Step 1: Get Essential Tools

To build your own RPM you require some of the tools fo the building process. So run the following command for setting build environment for RPM

[root@localhost ~]# yum install rpm-build rpmdevtools tree

Step 2: Directory Structure Environment

For building process, there is a directory structure. You may create this directory structure anywhere you like to do. For this example, I am creating this structure in my root’s directory.

# cd /root/
# rpmdev-setuptree

Note: If above command ‘rpmdev-setuptree’ failed to execute or did not create your structure. Run the following command to get it done.

[root@localhost ~]# mkdir -p ~/rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS,tmp}

Now, When you will list your root’s directory you will see a directory with name rpm. Running tree command with rpm directory you can see whole directory structure.

[root@localhost ~]# ll
total 0
drwxr-xr-x. 2 root root 21 Jul 7 16:58 dump-1  --- This Directory Contain Your code
drwxr-xr-x. 8 root root 77 Jul 7 17:00 rpm
[root@localhost ~]# tree rpm
├── RPMS
└── tmp

Step 3: Write rpmMacro File

The RPM system defines a lot of handy macros so that your specification files can work regardless of where system directories are located. You simply have to use the macro, such as %_bindir, in place of hard-coded paths. The %_bindir macro, for example, identifies the default directory for binary executables, /usr/bin. You may use these macros wherever possible to avoid hard-coded paths and settings.
So for this example, you need a rpmmacro file in home directory file with the following contents. Read more about rpmmacro

Note: Change the values black bold text with according to your setup.

[root@localhost kapendra]# vim .rpmmacros

Sometimes there could be some pre-written text inside, so clear the file and copy below-written lines and fill these details

%packager Your_name
%_topdir /home/YOUR_HOME_DIR/rpm   ----- for me its /root/rpm
%_tmppath /home/YOUR_HOME_DIR/rpm/tmp  ----------for me its /root/rpm/tmp

Now save the file using :wq!

Step 4: Put Files in SOURCES Directory

Now I have a script for MySQL dump with name “mysql.sh” inside dump-1 directory. we need to copy all our files and script directory inside /root/rpm/SOURCES directory, (All these things will get add in RPM) and run the following command

[root@localhost ~]# mv /root/dump-1 /root/rpm/SOURCES
[root@localhost ~]# ll
total 0
drwxr-xr-x. 8 root root 77 Jul 7 17:00 rpm

Now check the structure of your file

[root@localhost ~]# tree /root/rpm/SOURCES/
└── dump-1
 └── mysql.sh

1 directory, 1 file

Now enter the SOURCE Directory and create a tarball or the dump-1 directory.

[root@localhost ~]# cd /root/rpm/SOURCES/
[root@localhost SOURCES]# tar -cvzf dump-1.tar.gz dump-1
[root@localhost SOURCES]# ll
total 4
drwxr-xr-x. 2 root root 21 Jul 7 17:28 dump-1
-rw-r--r--. 1 root root 148 Jul 7 17:29 dump-1.tar.gz

Step 5: Creating the Spec File

SPEC file direct the RPM in the build process. A spec file contains eight different sections, most of which are required. The SPEC file contents are known as the Preamble. The Preamble contains a wealth of information about the package being built, and the people that built it. You may read more about the preamble. So here’s dump’s preamble:

[root@localhost kapendra]# vim /root/rpm/SPECS/dump.spec

Clear all the content and Put the following content inside the file.

Name: dump
Version: 1
Release: 0
Summary: mysqldump script test rpm  
Source0: dump-1.tar.gz
License: GPL
Group: kapendra
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-buildroot
This is a testing package and we are testing for building a RPM
%setup -q
install -m 0755 -d $RPM_BUILD_ROOT/etc/dump
install -m 0755 mysql.sh $RPM_BUILD_ROOT/etc/dump/mysql.sh
echo <Processing . . . . .>
echo <put you text like installation successful>
%dir /etc/dump

After writing (pasting :P) all the lines and editing save the changes with :wq!

Note: Change package name, script path, archive name, description etc., (Black Bold Area) According to you need

Step 6: Start Building RPM

We have completed all the requirement and we have completed most of the configuration. So we may proceed for the building our rpm by executing following command.

[root@localhost SPECS]# cd /root/rpm
[root@localhost rpm]# rpmbuild -ba SPECS/dump.spec
Executing(%prep): /bin/sh -e /root/rpm/tmp/rpm-tmp.XZx40G
+ umask 022
+ cd /root/rpm/BUILD
+ cd /root/rpm/BUILD
+ rm -rf dump-1
+ /usr/bin/gzip -dc /root/rpm/SOURCES/dump-1.tar.gz
+ /usr/bin/tar -xf -
+ '[' 0 -ne 0 ']'
+ cd dump-1
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /root/rpm/tmp/rpm-tmp.Hv0g7R
+ umask 022
+ cd /root/rpm/BUILD
+ cd dump-1
+ exit 0
Executing(%install): /bin/sh -e /root/rpm/tmp/rpm-tmp.9kLNd3
+ umask 022
+ cd /root/rpm/BUILD
+ '[' /root/rpm/BUILDROOT/dump-1-0.x86_64 '!=' / ']'
+ rm -rf /root/rpm/BUILDROOT/dump-1-0.x86_64
++ dirname /root/rpm/BUILDROOT/dump-1-0.x86_64
+ mkdir -p /root/rpm/BUILDROOT
+ mkdir /root/rpm/BUILDROOT/dump-1-0.x86_64
+ cd dump-1
+ install -m 0755 -d /root/rpm/BUILDROOT/dump-1-0.x86_64/etc/dump
+ install -m 0755 mysql.sh /root/rpm/BUILDROOT/dump-1-0.x86_64/etc/dump/mysql.sh
+ /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /root/rpm/BUILD/dump-1
/usr/lib/rpm/sepdebugcrcfix: Updated 0 CRC32s, 0 CRC32s did match.
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: dump-1-0.noarch
Provides: dump = 1-0
Requires(interp): /bin/sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires(post): /bin/sh
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpm/BUILDROOT/dump-1-0.x86_64
Wrote: /root/rpm/SRPMS/dump-1-0.src.rpm
Wrote: /root/rpm/RPMS/noarch/dump-1-0.noarch.rpm
Executing(%clean): /bin/sh -e /root/rpm/tmp/rpm-tmp.DZbBFB
+ umask 022
+ cd /root/rpm/BUILD
+ cd dump-1
+ rm -rf /root/rpm/BUILDROOT/dump-1-0.x86_64
+ exit 0

Step 7: Verify Your Work

After the successful build, in the output, you will find a line like Wrote: /root/rpm/RPMS/noarch/dump-1-0.noarch.rpm in means you have successfully build your own RPM.

Now you can check your work by installing your rpm using the command “rpm  -ivh dump-1-0.noarch.rpm “and check for the installed files as per your SPEC file.

[root@localhost noarch]# cd /root/rpm/RPMS/noarch
[root@localhost noarch]# rpm -ivh dump-1-0.noarch.rpm 
Preparing... ################################# [100%]
Updating / installing...
 1:dump-1-0 ################################# [100%]
Processing . . . . .
put you text like installation successful.
[root@localhost noarch]# ll /etc/dump/
total 0
-rwxr-xr-x. 1 root root 0 Jul 7 17:33 mysql.sh

Hope this tutorial was interesting and you find it helpful. Feel free to comment  and share


Video Coming Soon: