Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Install AlmaLinux 8 with kickstart and virt-install

I have previously written about deploying the new-defunct CentOS 8, and now here is the replacement.

I am pleased with the design direction of the installer. It now handles invalid package names in the %packages set. It paused to ask, "These packages are not available, do you want to proceed without them?" Before, it would just fail out with "Invalid package selection," and leave it up to the admin to go poke through the logs to find what package failed. Also, my deployment is only 12 minutes long. I seem to remember in the past that it would take 27 minutes, but thatwas specifically for Fedora. I haven't deployed a CentOS 7 or 8 vm in a long time so I don't recall that deployment time specifically.

The kickstart file

# File: /mnt/public/Support/Platforms/AlmaLinux8/almalinux8-ks.cfg
# Locations:
#    /mnt/public/Support/Platforms/AlmaLinux8/almalinux8-ks.cfg
# Author: bgstack15
# Startdate: 2017-06-02
# Title: Kickstart for AlmaLinux 8 for ipa.internal.com
# Purpose: To provide an easy installation for VMs and other systems in the Internal network
# History:
#    2017-06 I learned how to use kickstart files for the RHCSA EX-200 exam
#    2017-08-08 Added notifyemail to --extra-args
#    2017-10-29 major revision to use local repository
#
#
#
#
#    2019-09-24 fork for CentOS 8
#    2020-11-08 update for 2004 iso
#    2022-03-18 change to AlmaLinux 8
# Usage with virt-install:
#    vm=a8-01a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=centos8 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/AlmaLinux-8.5-x86_64-minimal.iso --initrd-inject=/mnt/public/Support/Platforms/AlmaLinux8/almalinux8-ks.cfg --extra-args "inst.ks=file:/almalinux8-ks.cfg SERVERNAME=${vm} NOTIFYEMAIL=bgstack15@gmail.com net.ifnames=0 biosdevname=0" --debug --network type=bridge,source=br0 --noautoconsole
#    vm=c8-02a; sudo virsh destroy "${vm}"; sudo virsh undefine --remove-all-storage "${vm}";
# Reference:
#    https://sysadmin.compxtreme.ro/automatically-set-the-hostname-during-kickstart-installation/
#    /mnt/public/Support/Platforms/CentOS7/install-vm.txt

#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
#install # NO LONGER USED, ALMALINUX8
# Keyboard layouts
keyboard 'us'
# Root password
rootpw --plaintext plaintextexamplepw
# my user
user --groups=wheel --name=bgstack15-local --password=$6$.gh9u8vg2HDJPPX/$g3X2l.q75gs7r0UKnt6h88bD8o1mSGsj/1DGNUzebMzb0TBh8of4iN6WyxYs/y379UiqgEPqqsYOI5FNrXNUa. --iscrypted --gecos="bgstack15-local"

# System language
lang en_US.UTF-8
# Firewall configuration
firewall --enabled --ssh
# Reboot after installation
reboot
# Network information
#attempting to put it in the included ks file that accepts hostname from the virsh command.
#network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate
%include /tmp/network.ks
# System timezone
timezone America/New_York --utc
# System authorization information
auth  --useshadow  --passalgo=sha512
# Use network installation instead of CDROM installation media
url --url="http://www.example.com/mirror/almalinux/8/BaseOS/x86_64/os"
# WORKHERE, point to my mirror
#url --url="http://ord.mirror.rackspace.com/almalinux/8/BaseOS/x86_64/os"

# Use text mode install
text
# SELinux configuration
selinux --enforcing
# Do not configure the X Window System
skipx

# Use all local repositories
# Online repos
repo --name=internalrpm --baseurl=http://www.example.com/internal/repo/rpm/
repo --name=internalel8 --baseurl=http://www.example.com/internal/repo/rpm-el8/
repo --name=copr-bgstack15-stackrpms --baseurl=https://www.example.com/mirror/copr-bgstack15-stackrpms/epel-$releasever-$basearch/
repo --name=base --baseurl=https://www.example.com/mirror/almalinux/$releasever/BaseOS/$basearch/os/
repo --name=appstream --baseurl=https://www.example.com/mirror/almalinux/$releasever/AppStream/$basearch/os/
repo --name=extras --baseurl=https://www.example.com/mirror/almalinux/$releasever/extras/$basearch/os/
repo --name=powertools --baseurl=https://www.example.com/mirror/almalinux/$releasever/PowerTools/$basearch/os/
repo --name=epel --baseurl=https://www.example.com/mirror/fedora/epel/$releasever/Everything/$basearch

# Offline repos
#
#
#
#
#

firstboot --disabled

# System bootloader configuration
bootloader --location=mbr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
autopart --type=lvm

%pre
echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname renameme.ipa.internal.com" > /tmp/network.ks
for x in $( cat /proc/cmdline );
do
   case $x in
      SERVERNAME*)
         eval $x
         echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname ${SERVERNAME}.ipa.internal.com" > /tmp/network.ks
         ;;
      NOTIFYEMAIL*)
         eval $x
         echo "${NOTIFYEMAIL}" > /mnt/sysroot/root/notifyemail.txt
     ;;
   esac
done
cp -p /run/install/repo/ca-ipa.internal.com.crt /etc/pki/ca-trust/source/anchors/ 2>/dev/null || :
wget http://www.example.com/internal/certs/ca-ipa.internal.com.crt -O /etc/pki/ca-trust/source/anchors/ca-ipa.internal-wget.com.crt || :
update-ca-trust || :
%end

%post
(
   # Set temporary hostname
   #hostnamectl set-hostname renameme.ipa.internal.com;

   # Get local mirror root ca certificate
   wget http://www.example.com/internal/certs/ca-ipa.internal.com.crt -O /etc/pki/ca-trust/source/anchors/ca-ipa.internal.com.crt && update-ca-trust

   # Get local mirror repositories
   wget https://www.example.com/internal/Support/Platforms/almalinux8/set-my-repos.sh --output-document /usr/local/sbin/set-my-scripts.sh ; chmod +x /usr/local/sbin/set-my-scripts.sh ; sh -x /usr/local/sbin/set-my-scripts.sh

   # NONE TO REMOVE dnf -y remove dnfdragora ;
   yum clean all ;
   yum update -y ;

   # Remove graphical boot and add serial console
   sed -i -r -e '/^GRUB_CMDLINE_LINUX=/{s/(\s*)(rhgb|quiet)\s*/\1/g;};' -e '/^GRUB_CMDLINE_LINUX=/{s/(\s*)\"$/ console=ttyS0 console=tty1\"/;}' /etc/default/grub
   grub2-mkconfig > /boot/grub2/grub.cfg

   # Send IP address to myself
   thisip="$( ifconfig 2>/dev/null | awk '/Bcast|broadcast/{print $2}' | tr -cd '[^0-9\.\n]' | head -n1 )"
   {
      echo "${SERVER} has IP ${thisip}."
      echo "system finished kickstart at $( date "+%Y-%m-%d %T" )";
   } | $( find /usr/share/bgscripts/send.sh /usr/bin/send 2>/dev/null | head -n1 ) -f "root@$( hostname --fqdn )" \
      -h -s "${SERVER} is ${thisip}" $( cat /root/notifyemail.txt 2>/dev/null )

   # No changes to graphical boot
   #

   # fix the mkhomedir problem
   systemctl enable oddjobd.service && systemctl start oddjobd.service

   # Personal customizations
   mkdir -p /mnt/bgstack15 /mnt/public
   su bgstack15-local -c "sudo /usr/bin/bgconf.py"

) >> /root/install.log 2>&1
%end

%packages
@core
@^minimal install
bc
bgconf
bgscripts-core
bind-utils
cifs-utils
cryptsetup
curl
dosfstools
epel-release
expect
firewalld
git
iotop
ipa-client
-iwl*-firmware
locale-en_BS
mailx
man
mlocate
net-tools
nfs-utils
p7zip
parted
postfix
python3-policycoreutils
rpm-build
rsync
screen
strace
sysstat
tcpdump
telnet
vim
wget
yum-utils
%end

Now slightly more prominent than before, is my set-my-repos.sh script. I adapted this from one I wrote for my Devuan GNU+Linux installations. Here is my rpm-based version:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/bin/sh
# File: /mnt/public/Support/Platforms/AlmaLinux8/set-my-repos.sh
# Location:
# Author: bgstack15
# Startdate: 2019-08-10 16:02
# Title: Script that Establishes the repos needed for GNU/Linux
# Purpose: Set up the 3 repos I always need on devuan clients
# History:
#     2019-09-24 forked from devuan set-my-repos.
#     2022-03-18 changed from C8 to A8, changed if-then line #44 to not use ! and instead use : else
# Usage:
#    sudo set-my-repos.sh
# Reference:
#    /mnt/public/Support/Platforms/devuan/devuan.txt
# Improve:
# Documentation:

ALLREPOSGLOB="/etc/yum.repos.d/*.repo"
REPOSBASE="/etc/yum.repos.d"

# confirm key
confirm_key() {
   # call: confirm_key "${SEARCHPHRASE}" "${URL_OF_KEY}"
   ___ck_repo="${1}"
   ___ck_sp="${2}"
   ___ck_url="${3}"
   if rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' 2>/dev/null | grep -qe "${___ck_sp}" ;
   then
      :
   else
      # not found so please add it
      echo "Adding key for ${___ck_repo}" 1>&2
      wget -O- "${___ck_url}" | sudo rpm --import -
   fi
}

# confirm repo
confirm_repo_byurl() {
   # call: confirm_repo "${REPO_FILENAME}" "${REPO_FILE_URL}" "${SEARCHGLOB}"
   ___cr_repo="${1}"
   ___cr_url="${2}"
   ___cr_sf="${3}"
   # if we cannot find a file matching the requested name in the glob
   if ! grep -q -F -e "${___cr_repo}" ${ALLREPOSGLOB} 2>/dev/null ;
   then
   #   :
   #else
      # not found so please download it
      echo "Adding repo ${___cr_repo}" 1>&2
      wget -O- "${___cr_url}" --quiet >> "${REPOSBASE}/${___cr_sf}"
   fi
}

# REPO 1: internal bundle
confirm_repo_byurl "[baseos-internal]" "https://www.example.com/internal/repo/mirror/internal-bundle-almalinux8.repo" "internal-bundle-almalinux8.repo"
# It is a good idea to run this too.
distro=almalinux8 ; grep -oP "(?<=^\[).*(?=-internal])" /etc/yum.repos.d/internal-bundle-${distro}.repo | while read thisrepo; do yum-config-manager --disable "${thisrepo}"; done

# REPO 2: local internalrpm
confirm_repo_byurl "[internalrpm]" "https://www.example.com/internal/repo/rpm/internalrpm.repo" "internalrpm.repo"
wget --continue "https://www.example.com/internal/repo/rpm/internalrpm.mirrorlist" --output-document "${REPOSBASE}/internalrpm.mirrorlist" --quiet

# REPO 3: copr
# yum will download key and ask for confirmation during first use.
confirm_repo_byurl "[copr:copr.fedorainfracloud.org:bgstack15:stackrpms]" "https://www.example.com/internal/repo/mirror/bgstack15-stackrpms-epel-8.repo" "bgstack15-stackrpms-epel-8.repo"

And that script above calls file internal-bundle-almalinux8.repo which has these contents.

# internal-bundle-almalinux8.repo
# Install with:
# distro=almalinux8 ; sudo wget https://www.example.com/internal/repo/mirror/internal-bundle-${distro}.repo -O /etc/yum.repos.d/internal-bundle-${distro}.repo && grep -oP "(?<=^\[).*(?=-internal])" /etc/yum.repos.d/internal-bundle-${distro}.repo | while read thisrepo; do sudo yum-config-manager --disable "${thisrepo}"; done
# 2022-03-18 incomplete! needs to point to local.

[baseos-internal]
name=AlmaLinux $releasever - BaseOS internal
#mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/baseos
#baseurl=https://repo.almalinux.org/almalinux/$releasever/BaseOS/$basearch/os/
baseurl=https://www.example.com/mirror/almalinux/$releasever/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux

[appstream-internal]
name=AlmaLinux $releasever - AppStream internal
#mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/appstream
#baseurl=https://repo.almalinux.org/almalinux/$releasever/AppStream/$basearch/os/
baseurl=https://www.example.com/mirror/almalinux/$releasever/AppStream/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux

[extras-internal]
name=AlmaLinux $releasever - Extras internal
#mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/extras
#baseurl=https://repo.almalinux.org/almalinux/$releasever/extras/$basearch/os/
baseurl=https://www.example.com/mirror/almalinux/$releasever/extras/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux

[powertools-internal]
name=AlmaLinux $releasever - PowerTools internal
#mirrorlist=https://mirrors.almalinux.org/mirrorlist/$releasever/powertools
#baseurl=https://repo.almalinux.org/almalinux/$releasever/PowerTools/$basearch/os/
baseurl=https://www.example.com/mirror/almalinux/$releasever/PowerTools/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux

[epel-internal]
name=EPEL for AlmaLinux 8 - $basearch internal
#metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-8&arch=$basearch
#baseurl=http://download.fedoraproject.org/pub/epel/8/$basearch
baseurl=https://www.example.com/mirror/fedora/epel/$releasever/Everything/$basearch
#failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8

Obviously I mirror these repositories for myself, ergo the example.com baseurls.

Comments