Eric Radman : a Journal

Automated RHEL/Fedora Installation

Any time a task needs to be repeated it is a good candidate for automation. Any time a task needs to be reproducible automation is required. Lately I have been running frequent experiments on my home lab, and the ability to quickly rebuild a machine with custom parameters is of immense benefit.

Disk Images

Many of the Rocky Linux mirrors allow rsync, but a more space-efficient method is to use copy files from the installation ISO.

ISO Mount
Rocky-8.10-x86_64-dvd1.iso /var/www/htdocs/pub/rocky8
Rocky-9.4-x86_64-dvd.iso /var/www/htdocs/pub/rocky9
Fedora-Everything-netinst-x86_64-41-1.4.iso /var/www/htdocs/pub/fedora41

Installation sources may be remain mounted or copied.

Fedora netinst image is available at https://alt.fedoraproject.org/.

PXE Boot

The syslinux package includes the libraries for running a standard BIOS pxelinux

mkdir -p /tftpboot/pxelinux.cfg
for fn in pxelinux.0 ldlinux.c32 menu.c32 libutil.c32; do
    ./rinstall -m 644 $fn /tftpboot/
done

Where the DHCP options include the server running TFTP, the image to load, and the host-name for Anaconda to use

next-server 192.168.2.20;

host SFDEV1 {
    hardware ethernet 00:0c:29:f9:6d:4e;
    fixed-address 192.168.2.22;
    filename "pxelinux.0";
    option host-name "sfdev1";
}

The initial ramdisk and kernel can be taken from the install ISO

mkdir -p /tftpboot/{rocky8,rocky9}
cp /var/www/htdocs/pub/rocky8/isolinux/{vmlinuz,initrd.img} /tftpboot/rocky8
cp /var/www/htdocs/pub/rocky9/isolinux/{vmlinuz,initrd.img} /tftpboot/rocky9

The file name then starts with 01- followed by the MAC

# /tftpboot/pxelinux.cfg/01-00-0c-29-47-1b-a0
DEFAULT menu.c32
PROMPT 0
TIMEOUT 30
MENU TITLE PXE Menu
LABEL Install Rocky Linux 8
  KERNEL rocky8/vmlinuz
  APPEND initrd=rocky8/initrd.img inst.repo=http://192.168.2.20/pub/rocky8 inst.ks=http://192.168.2.20/pub/rocky8-ks.cfg

iPXE Loader

If the machine is booting with UEFI and iPXE the configuration is similar

#!ipxe
set base-url http://192.168.2.20/pub
kernel /rocky8/vmlinuz initrd=initrd.img ip=dhcp inst.repo=${base-url}/rocky8 inst.ks=${base-url}/rocky8-ks.cfg
initrd /rocky8/initrd.img
boot

Anaconda for Rocky/Alma Linux

url --url="http://192.168.2.20/pub/rocky9/"

keyboard --vckeymap=us --xlayouts=us
lang en_US.UTF-8

text
skipx
reboot

selinux --disabled
firewall --disabled

rootpw ******
user --name=eradman --groups=wheel --iscrypted --password="$crypted_pass"
sshkey --username=eradman "ssh-ed25519 AAAA.... eradman@t460s.eradman.com"
timezone US/Eastern

ignoredisk --only-use=sda
bootloader --location=mbr --timeout=1 --boot-drive=sda
zerombr
clearpart --all --initlabel

part /boot --fstype ext4 --size 600 --ondisk sda --asprimary
part swap --recommended --ondisk sda
part / --fstype ext4 --size 10000 --grow --ondisk sda

%packages
@minimal-environment
glibc-langpack-en
net-tools
sudo
wget
-iwl*firmware
%end

%post --log=/root/kickstart-post.log
set -x
echo "%wheel  ALL=(ALL)  NOPASSWD: ALL" >> /etc/sudoers
/usr/bin/systemctl enable sshd
%end

Anaconda for Fedora

The Fedora installation is very similar, although the Workstation packages are not available from the install image.

url --url="https://mirrors.rit.edu/fedora/fedora/linux/releases/38/Everything/x86_64/os/"

keyboard --vckeymap=us --xlayouts=us
lang en_US.UTF-8

reboot
firewall --enabled --ssh

rootpw ******
user --name=eradman --groups=wheel --iscrypted --password="$2b...."
sshkey --username=eradman "ssh-ed25519 AAAA.... eradman@t460s.eradman.com"
timezone US/Eastern

ignoredisk --only-use=sda
zerombr
clearpart --all --initlabel
autopart --type lvm --fstype ext4

%packages
@workstation-product-environment
%end

%post --log=/root/kickstart-post.log
set -x
echo "%wheel  ALL=(ALL)  NOPASSWD: ALL" >> /etc/sudoers
/usr/bin/systemctl enable sshd
%end

Device Detection

VMware will present hard disks as SCSI devices, so sda will be the first disk. On other virtualization platforms such as Bhyve the first device will be a virtio block device named vda. One trick is to detect which device exists in the %pre section and write out some configuration to be included in the main kickstart section

# ...
%include /tmp/part-include
# ...

%pre
if [ -d /sys/block/vda ]; then
  ROOTDEV="/dev/vda"
else
  ROOTDEV="/dev/sda"
fi

cat << EOF > /tmp/part-include
clearpart --all --drives=$ROOTDEV --initlabel
EOF
%end

Generating Passwords

Passwords for use with useradd(1)/usermod(1) can be generated using python:

sudo dnf -y install python3-bcrypt
python3 -c 'import bcrypt; print(bcrypt.hashpw(b"******", bcrypt.gensalt(rounds=15)).decode("ascii"))'

References