How to do fast, repeatable Linux installations #2 — Bash scripts + RPM

0

In Episode 1, How to do fast, repeatable Linux installations #1 — Bash scripts, I discussed how I used a Bash script after performing a basic Fedora installation to perform a series of post-installation tasks that can’t be performed by the standard installer. This saved me a great deal of time and effort dealing with multiple installations each day.

That was a great solution for a number of years, but I began to add tasks to the script that caused it to become more complicated. I also decided for a number of reasons that it might be a good idea to use an RPM to perform many of those tasks for me. I also wanted to learn how to create RPMs as an exercise. So I decided to create an RPM to install several tools including the postinstall.sh script, perform some configuration tasks, and prompt the user to run the postinstall.sh script.

Most of the tools I installed were available from the Fedora repository and were intended to make the rest of the tasks required for my post-install work easier to perform. This included tools like screen and Midnight Commander (mc) so I could perform some manual tasks while postinstall.sh was still running, while using my familiar and favorite tools. I used the RPM I created for several years, making a large number of modifications to it in order to keep up with changes to Fedora and changes to the tasks I wanted it to perform.

How to Build RPMs

In a previous article, How to build rpm packages, I explained how to — you guessed it — build RPM packages. Once built, the simple package created in that article could be installed like any other RPM package.

Since that previous article covers all the details of how to — well — build RPM packages, I won’t cover that here. So read that article and build the RPM it describes so that you can return here and use the information in the rest of this article to build your own postinstall RPM.

Warning!!! — Don’t use the RPM created in this article on a production host. This article and the code that goes with it are intended as a tool to demonstrate what can be done with an RPM and a Bash program to perform post-installation tasks. Use a non-production VM if you want to experiment with this project.

The spec file

The spec file in Figure 1 is a modified version of the one I used. I’ve removed the installs for some applications, desktop themes, and wallpapers, that are not necessary for a demonstration such as this. I’ve also removed some tasks from the %post section that are no longer necessary on current Fedora releases.

################################################################################
# Spec file for Davids post-installation utilities
# David Both
################################################################################
# Configured to be built by non-root user
################################################################################
################################################################################
################################################################################
# WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!        #
#                                                                              #
# DO NOT USE THE RPM CREATED BY THIS SPEC FILE IN A PRODUCTION ENVIRONMENT!!!  #
# This spec file and the RPM it creates is intended only for educational       #
# purposes and should never be used in a production environment.               #
#                                                                              #
# WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!        #
################################################################################
################################################################################
################################################################################
#
Summary: A collection of Fedora tools, configuration files, and administrative utility programs mostly written in BASH.
Name: postinstall
Version: 2.6
Release: 5   
License: GPL2
URL: https://www.both.org
Group: System
Packager: David Both LinuxGeek@both.org
Vendor: David Both
Requires: bash 
Requires: wget 
Requires: deltarpm 
Requires: mc 
Requires: dmidecode
Requires: screen

# Build with the following syntax:
# rpmbuild --target noarch -bb postinstall.spec

%description
This package is a collection of BASH scripts, wallpapers, fonts, and tools that I have
developed over the years to perform various useful administrative tasks. 

This RPM and the tools it installs is for testing and edulcationanl purposes only!
Do not use it in a production environment.

Backups - A backup program called rsbu. Configuration is in /usr/local/etc/rsbu.conf
sysdata - A program that can collect a very large amount of data about your Linux computer.
createMOTDLinux - Creates an MOTD with current data about 
          your computer.
create_motd - with a link in cron.daily, runs createMOTDLinux 
          each day with the correct options.
postinstall.sh - A script to perform all of the usual configuration
          tasks that I perform on newly installed systems. This script
          takes up to 2 hours to complete if everything is installed but
          it saves me much time and typing. It includes installing all
          available updates. It copies some favorite default
          configurations for Midnight Commander, NTP, and makes some
          changes to GRUB configuration. It installs a large number
          of compatibility and other useful fonts. It can
          also install many of the servers I use on a server host.
LogBanner - A banner that is used as a security warning prior to remote
          logins.
UpgradeFedora - A BASH script to upgrade Fedora from one version to the next using
          dnf system-upgrade.
 ...and more.

This RPM also does the following:
-  Adds a symlink to /etc/cron.daily to point to /usr/local/bin/create_motd.
-  Appends a new alias (lsn) to /etc/bashrc to specifically use the color=no
   option with ls.
-  Installs a script, /root/postinstall.sh, which can be run by root and
   automatically installs some other useful packages if they are not already installed.

%prep
################################################################################
# Create the build tree and copy the files from the development directories    #
# into the build tree.                                                         #
################################################################################
echo "BUILDROOT = $RPM_BUILD_ROOT"
mkdir -p $RPM_BUILD_ROOT/etc/profile.d
mkdir -p $RPM_BUILD_ROOT/etc/glances
mkdir -p $RPM_BUILD_ROOT/root/mcconfigfiles/
mkdir -p $RPM_BUILD_ROOT/tmp
mkdir -p $RPM_BUILD_ROOT/usr/local/bin/
mkdir -p $RPM_BUILD_ROOT/usr/local/etc/
mkdir -p $RPM_BUILD_ROOT/usr/share/doc/postinstall/
mkdir -p $RPM_BUILD_ROOT/var/spool/cron


cp /home/dboth/development/utils/trunk/bash_logout $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/create_motd $RPM_BUILD_ROOT/usr/local/bin
cp /home/dboth/development/utils/trunk/doUpdates $RPM_BUILD_ROOT/usr/local/bin
cp /home/dboth/development/utils/trunk/GPL_LICENSE.txt $RPM_BUILD_ROOT/usr/share/doc/postinstall
cp /home/dboth/development/utils/trunk/ifcfg-ifnamehere* $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/iptables $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/LogBanner $RPM_BUILD_ROOT/etc/
cp /home/dboth/development/utils/trunk/glances.conf $RPM_BUILD_ROOT/etc/glances
cp -r /home/dboth/development/utils/trunk/mc/* $RPM_BUILD_ROOT/root/mcconfigfiles
cp /home/dboth/development/utils/trunk/misc-files/.toprc $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/myBashConfig.sh $RPM_BUILD_ROOT/etc/profile.d
cp /home/dboth/development/utils/trunk/mymotd $RPM_BUILD_ROOT/usr/local/bin
cp /home/dboth/development/utils/trunk/postinstall.sh $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/root.crontab $RPM_BUILD_ROOT/var/spool/cron/root
cp /home/dboth/development/utils/trunk/rsbu $RPM_BUILD_ROOT/usr/local/bin
cp /home/dboth/development/utils/trunk/rsbu.conf $RPM_BUILD_ROOT/usr/local/etc
cp /home/dboth/development/utils/trunk/sysdata $RPM_BUILD_ROOT/usr/local/bin
cp /home/dboth/development/utils/trunk/tmpwatch $RPM_BUILD_ROOT/root
cp /home/dboth/development/utils/trunk/UpgradeFedora.sh $RPM_BUILD_ROOT/root

%files
%attr(0600, root, root) /root/iptables
%attr(0644, root, root) %config /var/spool/cron/root
%attr(0644, root, root) %config /etc/LogBanner
%attr(0644, root, root) %config /etc/profile.d/myBashConfig.sh
%attr(0754, root, root) /usr/local/bin/rsbu
%attr(0644, root, root) %config /usr/local/etc/rsbu.conf
%attr(0755, root, root) /usr/local/bin/doUpdates
%attr(0755, root, root) /usr/local/bin/sysdata
%attr(0754, root, root) /usr/local/bin/create_motd
%attr(0755, root, root) /usr/local/bin/mymotd
%attr(0744, root, root) /root/postinstall.sh
%attr(0744, root, root) /root/UpgradeFedora.sh
%attr(0644, root, root) /root/.toprc
%attr(0644, root, root) /root/bash_logout
%attr(0754, root, root) /root/tmpwatch
%attr(0644, root, root) /root/mcconfigfiles/ini
%attr(0644, root, root) /root/mcconfigfiles/panels.ini
%attr(0744, root, root) /usr/share/doc/postinstall/GPL_LICENSE.txt
%attr(0644, root, root) /etc/glances/glances.conf

%pre

%post
################################################################################
# First get the distro info out of the file in a way that produces consistent  # 
# results for Fedora.                                                          #
################################################################################
Distro=`cat /etc/*elease* 2>/dev/null | grep release | uniq | sed -e "s/[lL]inux //g"`
if echo $Distro | grep Fedora > /dev/null
then
   # This is Fedora
   NAME="Fedora"
else
  # This is not Fedora so is not supported
  echo "Error: Unsupported distribution. This is not Fedora"
fi

echo "############ Name = $NAME ##############"

################################################################################
# Turn off PackageKit updates if it is installed.                              #
################################################################################
if [ -e /etc/yum/pluginconf.d/refresh-packagekit.conf ]
then
   cd /etc/yum/pluginconf.d/
   # Edit the refresh-packagekit.conf and set disabled
   sed -i -e "s/enabled=1/enabled=0/" refresh-packagekit.conf
fi
# do the same in the dnf directory
if [ -e /etc/dnf/pluginconf.d/refresh-packagekit.conf ]
then
   cd /etc/dnf/pluginconf.d/
   # Edit the refresh-packagekit.conf and set disabled
   sed -i -e "s/enabled=1/enabled=0/" refresh-packagekit.conf
fi

################################################################################
# Perform these tasks only if this is Fedora                                   #
################################################################################
if [ $NAME = "Fedora" ]
then
   # If the tmpwatch file does not aleady exist
   if [ ! -f /etc/cron.daily/tmpwatch ]
   then
      # Copy tmpwatch script to correct location
      cd /root
      cp tmpwatch /etc/cron.daily
   fi
fi

# Now create the motd file
echo "Creating the MOTD for $HOSTNAME"
/usr/local/bin/create_motd

# Print instructions about the postinstall.sh file.

echo "################################################################################"
echo "# The next step is to run doUpdates -vr to install all current updates. Then   #"
echo "# run the /root/postinstall.sh script as described in the next section.        #"
echo "#                                                                              #"
echo "#------------------------------------------------------------------------------#"
echo "#                                                                              #"
echo "# Now run the script /root/postinstall.sh to install some additional desirable #"
echo "# administrative packages. These inlcude screen, powertop, iftop,              #"
echo "# iptraf-ng, iotop and sysstat among others. It also installs                  #"
echo "# a number of useful fonts that provide close analogues to various common      #"
echo "# fonts used in other operating systems.                                       #"
echo "#                                                                              #"
echo "# Run ./postinstall.sh -h to display all of the options and help.              #"
echo "################################################################################"

%postun

%clean
cd ~/rpmbuild/
rm -rf BUILD*

%changelog
* Tue Jul 02 2024 David Both <david@both.org>
  - Modify for use in a Both.org article.
   ################################################################################
   ################################################################################
   ################################################################################
   # WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!        #
   #                                                                              #
   # DO NOT USE THE RPM CREATED BY THIS SPEC FILE IN A PRODUCTION ENVIRONMENT!!!  #
   # This spec file and the RPM it creates is intended only for educational       #
   # purposes and should never be used in a production environment.               #
   #                                                                              #
   # WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!   WARNING!!        #
   ################################################################################
   ################################################################################
   ################################################################################

Figure 1: The sample SPEC file for the post-install RPM.

Preparing to build the RPM

Follow the example in the article, How to build rpm packages, for how to prepare for building an RPM. To be a little more specific for this project, you’ll need to perform the following steps.

  1. Create a subdirectory of your home directory and name it development. You could use another name but that’s the one I like to use for my development projects.
  2. Copy the spec file from this article and paste it into a file named postinstall.spec in the development directory. Many spec files define the “buildroot” but we don’t need to do that since the default buildroot is the builder’s home directory.
  3. Create the build directory structure as described in How to build rpm packages.
  4. The %prep section of the spec file lists the files that the RPM will install and the locations from which those files are copied during the build. Be sure to change the name of my home directory to that of yours when you create those locations.
  5. Download the files listed in the %description section of the spec file and copy them to the locations from which they’ll be copied during the build. The downloads page of this site lists those files.
  6. Modify the %prep section where it copies the various files into the directory tree created at the top of this section. These modifications will include deleting — or at least commenting out — copying the files you don’t have or don’t want.
  7. In the %files section, delete the lines for any files that you’ve decided not to install.

Building the RPM

Build the RPM using this same section of How to build rpm packages as a guide, changing names as appropriate.

If the build process encounters errors, fix them and try the build again. I frequently get errors due to misspellings.

Installing the RPM

Remember, this entire project should only be performed in a non-production VM, espcially installing the RPM and running the scripts.

After building the RPM, install it on your VM. As part of this project, you should verify that at least some of the dependencies were installed and that the files were installed.

Running the postinstall.sh script

Try running the postinstall.sh script. It may throw some errors but this article is not about making that script or any others work correctly. This is simply about using the RPM to install this script along with some others, as well as some other tools and configuration files.

Final thoughts

This approach to configuring my Fedora installations like I want them worked for a few years. However, it was even more cumbersome than using just the script. It required intervention on my part because I first needed to install the RPM, and then run the postinstall.sh script. This two-part process took time, despite the fact that using the RPM package to deliver and install a lot of files made sense.

I also ran into problems if I needed to run the script again to fix a problem or to install updated versions of the scripts and configuration files. That sometimes caused more problems than it was intended to fix because it didn’t always check to see if a particular task had been performed previously. It could mangle some existing files.

So this was a less than ideal solution. I needed a better, more integrated approach. I’ll cover that in the next — and probably last — installment.

Leave a Reply