Knowledge Base

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

Fedora 41: Lessons learned

Operations for each new OS level release

I need to create a few new files.

  1. /mnt/public/www/domainname/repo/mirror/bgstack15-stackrpms-fedora-41.repo
  2. /mnt/public/www/domainname/repo/mirror/example-bundle-fedora41.repo

Lessons learned

  1. Fedora 41 now needs more than 2GB of RAM for the installation, despite the hardware overview saying 2GB is enough.
  2. If you experience the forever dots beneath "Starting automated install.Checking storage configuration...", the problem might be in your kickstart file. You might not be able to access one of the --repo values. You can learn which one by pressing CTRL+C on the text console, and letting it dump to the /tmp/anaconda-tb* file(s) for more details. Then you can find:

    WARNING org.fedoraproject.Anaconda.Modules.Payloads:    raise SourceSetupError(msg.format(name=respotiroy.name, details=str(e))) from None
    WARNING org.fedoraproject.Anaconda.Modules.Payloads:pyanaconda.modules.common.errors.payload.SourceSetupError: Failed to add the 'fedora-cisco-openh264' repository: Failed ot download metadata for repo 'fedora-cisco-openh264': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried
    

    It's a shame this couldn't be more visible, or offered to skip, but it is supposed to be an automated install. But an automated install should make errors more visible on the completely-stuck part.

  1. I had to update my set-my-repos-rpm.sh script to handle the new dnf configuration, which isn't as robust and simple as before, and definitely not as much as yum. Now, when you run dnf config-manager setopt ${reponame}.enabled=0 it manages state in /etc/dnf/repos.override.d/99-config_manager.repo. You can view current enabled repos as evaluated by dnf with dnf repolist. I prefer to set enabled=0 in the /etc/yum.repos.d/ file directly, but I can see why they would want state managed separately. I find it misleading to have enabled=1 in the real repo file, but it is disabled by that override file. But I have bigger problems so this one gets to slide for now.

New vm files

Kickstart

Minimal changes. The biggest problem was the lack of a local Fedora 41 fedora-cisco-openh264 repository. Anaconda installer fails to report this correctly and just bugs out and waits until you interrupt it and then it finally dumps a log for you to dig and find. No substantial changes.

files/2025/listings/fc41x-ks.cfg (Source)

  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
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File: /mnt/public/Support/Platforms/Fedora/fc41x-ks.cfg
# Locations:
#    /mnt/public/Support/Platforms/Fedora/fc41x-ks.cfg
# Author: bgstack15
# Startdate: 2017-08-16
# Title: Kickstart for Fedora 41 xfce 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-11-01 major revision to use local mirror
#    2017-11-04 converted for building directly into an iso file
#    2017-11-15 fedora 27
#    2018-05-05 fedora 28
#    2018-07-08 adjusted to use --network type=bridge,source=br0 instead of type=direct,source=eno1
#    2018-12-01 fedora 29
#    2019-05-05 fedora 30
#    2020-02-20 fedora 31
#    2020-05-05 fedora 32
#    2020-12-02 fedora 33
#    2021-05-04 fedora 34
#    2022-03-28 fedora 35
#    2022-12-08 Fedora 37
#    2023-12-09 Fedora 39
#    2025-01-13 Fedora 41 now needs more than 2048M memory
# Usage with virt-install:
#    vm=fc41x-01a ; time sudo virt-install -n "${vm}" --memory 4096 --vcpus=2 --os-variant=fedora32 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=30 -l /mnt/public/Support/SetupsBig/Linux/Fedora-Everything-netinst-x86_64-41-1.4.iso --initrd-inject=/mnt/public/Support/Platforms/Fedora/fc41x-ks.cfg --extra-args "inst.ks=file:/fc41x-ks.cfg SERVERNAME=${vm} NOTIFYEMAIL=bgstack15@gmail.com" --debug --network type=bridge,source=br0 --noautoconsole
#    vm=fc41x-01a; 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
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# Root password
rootpw --plaintext plaintextexamplepw
# my user
user --groups=wheel --name=bgstack15-local --password=$6$.gh9u7vg2HDJPPX/$g3X1l.q75fs7iEXAMPLE1F2EIo1YSGGj/1DGeUzzEXAMPLEh4of6iNYWyxws/EXAMPLEgETqOsYFI5XNrkaUe. --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="https://www.example.com/mirror/fedora/linux/releases/41/Everything/x86_64/os/"

# Use text mode install
text
# SELinux configuration
selinux --enforcing
# Prepare X to run at boot
xconfig --startxonboot

# Use all local repositories
# Online repos
repo --name=internalrpm --baseurl=https://www.example.com/internal/repo/rpm/
repo --name=fedora --baseurl=https://www.example.com/mirror/fedora/linux/releases/$releasever/Everything/$basearch/os/
repo --name=updates --baseurl=https://www.example.com/mirror/fedora/linux/updates/$releasever/Everything/$basearch/
repo --name=rpmfusion-free --baseurl=https://www.example.com/mirror/rpmfusion/free/fedora/releases/$releasever/Everything/$basearch/os/
repo --name=rpmfusion-free-updates --baseurl=https://www.example.com/mirror/rpmfusion/free/fedora/updates/$releasever/$basearch/
repo --name=copr-bgstack15-stackrpms --baseurl=https://www.example.com/mirror/copr-bgstack15-stackrpms/fedora-$releasever-$basearch/
repo --name=copr-bgstack15-aftermozilla --baseurl=https://www.example.com/mirror/copr-bgstack15-aftermozilla/fedora-$releasever-$basearch/
#repo --name=fedora-cisco-openh264 --baseurl=https://www.example.com/mirror/fedora-cisco-openh264/$releasever/$basearch/os/

firstboot --disabled

# System bootloader configuration
#bootloader --location=mbr
# Partition clearing information
clearpart --none --initlabel
# Disk partitioning information
ignoredisk --only-use=vda
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 -x
   # 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/repo/rpm/set-my-repos.sh --output-document /usr/local/sbin/set-my-repos.sh ; chmod +x /usr/local/sbin/set-my-repos.sh ; sh -x /usr/local/sbin/set-my-repos.sh

   #dnf -y remove dnfdragora ;
   #dnf clean all ;
   #dnf 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

   systemctl enable sendmail.service && systemctl start sendmail.service
   # 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 )

   # Ensure boot to runlevel 5
   systemctl set-default graphical.target

   # 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/share/bgconf/bgconf.py"
   tf=/etc/cron.d/01_init.cron
   touch "${tf}" ; chown root.root "${tf}" ; chmod 0600 "${tf}"
   cat <<-"EOFCRON" 1>"${tf}"
@reboot         root    su bgstack15-local -c "sudo /usr/bin/bgconf.py" 1>/root/clone.log 2>&1 ; rm -f /etc/cron.d/01_init.cron 1>/dev/null 2>&1 ; systemctl restart lightdm 1>/dev/null 2>&1 ;
EOFCRON

} 2>&1 | tee -a /root/install.log
%end

%packages
@core
@^xfce-desktop-environment
@xfce-apps
@xfce-media
autossh
bc
bgconf
bgscripts
bgscripts-core
bind-utils
cifs-utils
cryptsetup
-dnfdragora
-dnfdragora-updater
dosfstools
expect
-firefox
firewalld
freeipa-client
git
-gstreamer1-plugins-ugly*
-hplip
iotop
librewolf
lightdm-gtk
locale-en_BS
mailx
man
net-tools
newmoon
nfs-utils
numix-icon-theme-circle
p7zip
parted
plocate
python3-policycoreutils
qemu-guest-agent
rpm-build
rsync
scite
screen
sendmail
spice-vdagent
strace
sysstat
tcpdump
telnet
-thunderbird
vim
vlc
wget
xdg-themes-stackrpms
xfce4-whiskermenu-plugin
xrandr
%end

set-my-repos-rpm.sh

I needed some new syntax because dnf has changed how they operate, without backwards compatibility. So this has been minimally updated.

files/2025/listings/set-my-repos-rpm.sh (Source)

 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
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/bin/sh
# File: /mnt/public/www/internal/repo/rpm/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
#     2022-03-28 adapted to work with Fedora, C7, or A8
#     2025-01-13-2 13:22 adapted for Fedora 41/dnf5
# 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
}

# MAIN
distro="$( . /etc/os-release ; echo "${ID}${VERSION_ID%%.*}" )"
# calculate copr repo filename
copr_d=fedora
grep -qiE 'ID=.*(almalinux|centos|redhat|rocky)' /etc/os-release && copr_d=epel
copr_v="$( . /etc/os-release ; echo "${VERSION_ID%%.*}" )"

# REPO 1: internal bundle
bundle_name="[baseos-internal]"
grep -qiE 'ID=.*(fedora)' /etc/os-release && bundle_name="[fedora-internal]"
confirm_repo_byurl "${bundle_name}" "https://www.example.com/internal/repo/mirror/internal-bundle-${distro}.repo" "internal-bundle-${distro}.repo"
# It is a good idea to run this too.
# This setopt stuff seems to work, according to `dnf repolist` but it does not actually set "enabled=0" in the files which is confusing.
grep -oP "(?<=^\[).*(?=-internal])" /etc/yum.repos.d/internal-bundle-${distro}.repo | while read thisrepo; do yum-config-manager --disable "${thisrepo}" 2>/dev/null ; dnf config-manager --disable "${thisrepo}" 2>/dev/null || dnf config-manager setopt "${thisrepo}.enabled"=0 ; done

# REPO 2: local internalrpm
# no key; I never bothered. The LT-bfi1 resources somewhere in the mirror-$( date "+%F" ).7z files have a gpg key yum repo assets.
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-${copr_d}-${copr_v}.repo" "bgstack15-stackrpms-${copr_d}-${copr_v}.repo"

References

  1. My previous kickstart topics.
  2. Hard Knocks Senior High
  3. No thanks to the Internet
  4. How DNF's config-manager plugin technically works? - Fedora Discussion

Comments