Hi there!
Welcome to geekcoding101.com!
I have two decades years of working experiences on Linux. There are many things I have come across, but I want to say, building package for Linux is something you couldn't avoid at all in your work or study!
I have summarized the steps/tricks in this article, hope you will find it useful!
Enjoy!
Create unsigned rpm
I will first demonstrate how to create unsigned rpm.
Create Folder Structure
First step is creating folder structure.
If you don't specify top_dir in ~/.rpmmacros (It's a config file), then it will use ~/rpmbuild by default
cd ~ mkdir rpmbuild cd rpmbuild mkdir BUILD BUILDROOT SOURCES SRPMS RPMS SPECS
Create SPEC file for unsigned rpm
Now we can work on the spec file SPECS/rpm-no-sig.spec
:
# cat SPECS/rpm-no-sig.spec Name: rpm-no-sig Version: 1.0 Release: 1 Summary: This is a unsigned rpm. Vendor: Geekcoding101 License: Copyright (c) 2021 BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version} Packager: Geekcoding101 Source0: %{name}-%{version}.tar.gz %define INSTALL_DIR /usr/lib/unsigned-rpm/ %define INSTALL_FILE rpm-helper-unsigned.py %description %{Summary} This package provides rpm gpgcheck demo. %prep %setup -q %install rm -rf %{buildroot} install --directory %{buildroot}/%{INSTALL_DIR} install -m 0755 %{INSTALL_FILE} %{buildroot}/%{INSTALL_DIR} %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) %{INSTALL_DIR} %{INSTALL_DIR}/%{INSTALL_FILE} %exclude %{INSTALL_DIR}/*.pyc %exclude %{INSTALL_DIR}/*.pyo %doc %changelog * Sun Jan 21 2021 - Geekcoding101 - Initial commit. %post
Create a dummy source file for unsigned rpm
Use a dummy py file to be packed into the rpm: rpm-helper-unsigned.py
:
#!/usr/bin/env python import sys import os import re def main(): print("This is from unsigned rpm.") if __name__ == '__main__': main()
Create a folder: mkdir <rpm-name>-<version>
For example:
cd ~ mkdir rpm-no-sig-1.0
Then put rpm-helper-unsigned.py
under it.
Then make gz file for the folder:
tar cf rpm-no-sig-1.0.tar rpm-no-sig-1.0 gzip rpm-no-sig-1.0.tar
You will get file rpm-no-sig-1.0.tar.gz
.
Move it to SOURCES
folder.
When building rpm, it will recognize this gz file and extract it automatically.
Build rpm-no-sig.rpm
Run command: rpmbuild -ba SPECS/rpm-no-sig.spec
Example:
# rpmbuild -ba SPECS/rpm-no-sig.spec warning: bogus date in %changelog: Sun Jan 21 2021 - Geekcoding101 Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.ut6Q5z + umask 022 + cd /root/rpmbuild/BUILD + cd /root/rpmbuild/BUILD + rm -rf rpm-no-sig-1.0 + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/rpm-no-sig-1.0.tar.gz + /usr/bin/tar -xf - + STATUS=0 + '[' 0 -ne 0 ']' + cd rpm-no-sig-1.0 + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.UOxKuK + umask 022 + cd /root/rpmbuild/BUILD + '[' /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 '!=' / ']' + rm -rf /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 ++ dirname /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 + mkdir -p /root/rpmbuild/BUILDROOT + mkdir /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 + cd rpm-no-sig-1.0 + rm -rf /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 + install --directory /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64//usr/lib/unsigned-rpm/ + install -m 0755 rpm-helper-unsigned.py /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64//usr/lib/unsigned-rpm/ + '[' noarch = noarch ']' + case "${QA_CHECK_RPATHS:-}" in + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-compress + /usr/lib/rpm/redhat/brp-strip /usr/bin/strip + /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump + /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: rpm-no-sig-1.0-1.noarch warning: File listed twice: /usr/lib/unsigned-rpm/rpm-helper-unsigned.py Provides: rpm-no-sig = 1.0-1 Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PartialHardlinkSets) <= 4.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Requires: /usr/bin/env Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 Wrote: /root/rpmbuild/SRPMS/rpm-no-sig-1.0-1.src.rpm Wrote: /root/rpmbuild/RPMS/noarch/rpm-no-sig-1.0-1.noarch.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.w4KHSg + umask 022 + cd /root/rpmbuild/BUILD + cd rpm-no-sig-1.0 + rm -rf /root/rpmbuild/BUILDROOT/rpm-no-sig-1.0-1.x86_64 + exit 0
You will get RPMS/noarch/rpm-no-sig-1.0-1.noarch.rpm
Check MD5: rpm -Kv <rpm file>
Example:
# rpm -Kv RPMS/noarch/rpm-no-sig-1.0-1.noarch.rpm RPMS/noarch/rpm-no-sig-1.0-1.noarch.rpm: Header SHA1 digest: OK (84bd6662874a27ccd5cd3247ef7a4107c1919f54) MD5 digest: OK (198ab02bd5765c383c57dbe113551af0)
Backup this rpm to somewhere else.
Create signed rpm
Create SPEC file for signed rpm
The spec file SPECS/rpm-with-sig.spec
:
# cat SPECS/rpm-with-sig.spec Name: rpm-with-sig Version: 1.0 Release: 1 Summary: This is a signed rpm. Vendor: Geekcoding101 License: Copyright (c) 2021 BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version} Packager: Geekcoding101 Source0: %{name}-%{version}.tar.gz %define INSTALL_DIR /usr/lib/signed-rpm/ %define INSTALL_FILE rpm-helper-signed.py %description %{Summary} This package provides rpm gpgcheck demo. %prep %setup -q %install rm -rf %{buildroot} install --directory %{buildroot}/%{INSTALL_DIR} install -m 0755 %{INSTALL_FILE} %{buildroot}/%{INSTALL_DIR} %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) %{INSTALL_DIR} %{INSTALL_DIR}/%{INSTALL_FILE} %exclude %{INSTALL_DIR}/*.pyc %exclude %{INSTALL_DIR}/*.pyo %doc %changelog * Sun Jan 21 2021 - Geekcoding101 - Initial commit. %post
Create a dummy source file for signed rpm
Use a dummy py file to be packed into the rpm: rpm-helper-signed.py
. You can just reuse the one in above and change the print message accordingly.
Create a folder: cd ~ && mkdir <rpm-name>-<version>
Example: cd ~ && mkdir rpm-with-sig-1.0
Move rpm-helper-signed.py
into the folder.
Also create the gz file with same process.
Example:
tar cf rpm-with-sig-1.0.tar rpm-with-sig-1.0 gzip rpm-with-sig-1.0.tar
You will get file rpm-with-sig-1.0.tar.gz
.
Remove rpm-no-sig-1.0.tar.gz
from SOURCES
folder. Move rpm-with-sig-1.0.tar.gz
into SOURCES
.
Generate GPG key and Build rpm-with-sig.rpm
- Generate a gpg key for signing the rpm:
gpg --gen-key
- Check the new keys on your system:
gpg --fingerprint gpg --list-keys
- Update ~/.rpmmacros to specify which key to be used for signing:
%_gpg_name <secret key's last 8 digits>
- Build the rpm:
rpmbuild -ba SPECS/rpm-with-sig.spec
- You will get
RPMS/noarch/rpm-with-sig-1.0-1.noarch.rpm
- Sign the rpm:
rpm --addsign RPMS/noarch/rpm-with-sig-1.0-1.noarch.rpm
- Now you can check MD5 again:
rpm -Kv <rpm file>
Example:
# rpm -Kv ../rpm-with-sig-1.0-1.noarch.rpm ../rpm-with-sig-1.0-1.noarch.rpm: Header V4 RSA/SHA1 Signature, key ID 1ddb39c6: NOKEY Header SHA1 digest: OK (64fc89cf3eb3054e6316a77f4b22c183221ab13d) V4 RSA/SHA1 Signature, key ID 1ddb39c6: NOKEY MD5 digest: OK (fadae5f41bb0c939edbe865a974fce4c)
- You might see "NOKEY" in above output, because we didn't import the key into OS.
- Export your key:
gpg --export -a <last_8_dig_of_your_pub_key> > PUB_KEY_SIGNING_RPM
- Import it into RPM's database:
rpm --import PUB_KEY_SIGNING_RPM
- Now you can check MD5 again:
rpm -Kv rpm-with-sig-1.0-1.noarch.rpm
Example:
# rpm -Kv ../rpm-with-sig-1.0-1.noarch.rpm ../rpm-with-sig-1.0-1.noarch.rpm: Header V4 RSA/SHA1 Signature, key ID 1ddb39c6: OK Header SHA1 digest: OK (64fc89cf3eb3054e6316a77f4b22c183221ab13d) V4 RSA/SHA1 Signature, key ID 1ddb39c6: OK MD5 digest: OK (fadae5f41bb0c939edbe865a974fce4c)
Creating repo database/conf for unsigned rpm
Create repo database for the rpm-no-sig rpm
cd ~ mkdir unsigned_repo_with_rpm_no_sig cp rpm-no-sig-1.0-1.noarch.rpm unsigned_repo_with_rpm_no_sig createrepo --database unsigned_repo_with_rpm_no_sig/
Example:
# createrepo --database unsigned_repo_with_rpm_no_sig/ Spawning worker 0 with 1 pkgs Spawning worker 1 with 0 pkgs Spawning worker 2 with 0 pkgs Spawning worker 3 with 0 pkgs Workers Finished Saving Primary metadata Saving file lists metadata Saving other metadata Generating sqlite DBs Sqlite DBs complete
Create repo conf file for unsigned repo
# cat /etc/yum.repos.d/rpm-no-sig.repo [RPM-NO-SIG] name=rpm no sig repository baseurl=file:///root/unsigned_repo_with_rpm_no_sig enabled=1 gpgcheck=0 localpkg_gpgcheck=0 repo_gpgcheck=0 skip_if_unavailable=1
Creating signed repo database/conf/gpg for signed rpm
Generate GPG key and Create repo for the rpm-with-sig rpm
cd ~ mkdir signed_repo_with_rpm_with_sig cp rpm-with-sig-1.0-1.noarch.rpm signed_repo_with_rpm_with_sig createrepo --database signed_repo_with_rpm_with_sig/
Generate a new gpg key for signing the repo: gpg --gen-key
Create asc file:
gpg --detach-sign --armor -r Ox<secret key's last 8 digits fingerprint> signed_repo_with_rpm_with_sig/repodata/repomd.xml
It will generate signed_repo_with_rpm_with_sig/repodata/repomd.xml.asc
.
Create repo conf file for signed repo
# cat /etc/yum.repos.d/rpm-with-sig.repo [RPM-WITH-SIG] name=rpm with sig repository baseurl=file:///root/signed_repo_with_rpm_with_sig enabled=1 gpgcheck=1 localpkg_gpgcheck=1 repo_gpgcheck=1 skip_if_unavailable=1
RPM/YUM relevant GPG knowlege
There are two types of GPG keyrings used on RPM-based systems:
- RPM's GPG keyring. This keyring is used for verifying signatures on RPM packages. This can be check by
gpg
without specifyinghomedir
. - YUM's GPG keyring. This keyring is used for verifying signatures on repository metadata. There is one keyring per repository on the system. Once scanned the repo by
yum repolist
, you could find the gpg folder like this:/var/lib/yum/repos/x86_64/7/<your_repo_name>/gpgdir
. You could usegpg
commandADD/LIST/DELETE
keys as below:
sudo gpg --homedir /var/lib/yum/repos/x86_64/7/<your_repo_name>/gpgdir --delete-key <keyid>
YUM clean up
yum clean all
will not remove everything. In order to do a real clean, you could try this:
yum clean all rm -fr /var/lib/yum/repos/x86_64/7/<your_repo_name> rm -fr /var/cache/yum/x86_64/7/<your_repo_name>
Yum commands references
yum install <rpm name> yum install <path of the rpm> yum clean all yum clean metadata yum-config-manager yum-config-manager <rpm name>
Q/A
Can't remove keys from RPM due to duplicate entries
You might hit problem that there are duplicate entries in rpm -qa gpg-pub*
with same fingerprints.
rpm -e gpg-pubkey-xxxx
can't remove any.
You should use rpm -e --all-matches gpg-pubkey-xxxx
All right!
That's all for my sharing today!
Hope you find it useful!
Bye!