If you spin up virtual machines as much as I do, you may find it very tedious typing prompts and clicking buttons when installing CentOS 8. It may also be very time consuming when you have multiple virtual machines to configure.

If you are wondering if there is a way to automate the configuration process, well you're in luck! In this post, I'll show you how to create a kickstart file for CentOS 8 and then I'll apply it to KVM.  However before I begin, I have to thank my buddy Chris Kennedy for showing me how kickstart files work, go checkout his website for his weekly podcast.


Creating the Kickstart File

A kickstart files is just a text file, but contains instructions on how to setup the operating system. You can view the kickstart file for CentOS 8 in the /root directory. Look for a file named anaconda-ks.cfg, copy the contents of this file to a text editor.

By default this kickstart file was created by going through the installer for CentOS 8 and selecting the minimum software option. I'm going to make some changes like the passwords for the root user and myAdminUser, if you wish to change the username you may do so.

To change the password, I'll be using the openssl command.

openssl passwd -6 <YOUR_PASSWORD>

The passwd option will hash the password and -6 will hash the password using SHA 512. Copy the output of the openssl command and put it as the password for your kickstart file.

Great now scroll down to the Network information section and change the --hostname option. Since this host is going to be part of my Kubernetes cluster, I'll name it k8s-001. It's in this section you may switch out the DHCP option to static or add custom nameservers.

Let's move on to the %packages section, here I'll add the packages for vim, net-tools, and tmux.

The final addition, I'll include in the kickstart file, is the %post section. This section is for the post script that will be executed at the end of the installation. It's at this step that updates to packages will be installed along with a text file containing "hello 123" will be created. I'll add the following lines in the bottom of the file.

%post
yum update -y
yum upgrade -y
echo "hello 123" >> /tmp/hello.txt

%end

The full kickstart file looks like this:

#version=RHEL8
ignoredisk --only-use=vda
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda
autopart --type=lvm
# Partition clearing information
clearpart --all --initlabel --drives=vda
# Use text mode install
text
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
# Use CDROM installation media
cdrom
# Keyboard layouts
keyboard --vckeymap=us --xlayouts=''
# System language
lang en_US.UTF-8

# Network information
network  --bootproto=dhcp --device=enp1s0 --ipv6=auto --no-activate
network  --hostname=k8s-001
# Root password
rootpw --iscrypted $3$0Ps8/l7Uoasdl3LO98xQOv$Pm/mapo4$uifFYS.VhFa212YDX2G/NRe5mk/9noKZfkPO2uZ4BFc5ktcvmMHhtPHMlBepaWDNHqsas12
# Run the Setup Agent on first boot
firstboot --enable
# Do not configure the X Window System
skipx
# System services
services --enabled="chronyd"
# System timezone
timezone America/New_York --isUtc
user --name=myAdminUser --password$3$Ps357NRfDqbqPPnmySj$j.7.fzkQVoRYVt6ufasdjPRlpBZNhIbxs.maGQt.vplFjc1Ylf/RWJ6GoFWWklkloler7S8Vp2nSw06nD/ --iscrypted

%packages
@^minimal-environment
kexec-tools
vim
net-tools
tmux

%end

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

%post
yum update -y
yum upgrade -y
echo "hello 123" >> /tmp/hello.txt

%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

Before using the kickstart file, I'll validate the file using the ksvalidator command. If the command isn't present, install the pykickstart package.

ksvalidator anaconda-ks.cfg

The command SHOULD NOT return an output if the syntax of the kickstart file is correct.


Applying the Kickstart File

Cool, now that the kickstart file is created, it's time to use it when I create more virtual machines in KVM. I'll be using this creation script, I created for KVM:

#!/bin/sh

echo " creating VM now  "

echo -n " Enter hostname: "
read HNAME

echo -n " Hard drive size? (In GB): "
read HDSIZE

echo -n " Memory size? (In MB): "
read MEMSIZE

echo -n " Number of CPUs? "
read CPUS

virt-install --name $HNAME \
    --disk path=/appl/images/$HNAME.qcow2,bus=virtio,size=$HDSIZE \
    --graphics=none \
    --os-type=linux \
    --os-variant=centos \
    --vcpu=$CPUS \
    --ram=$MEMSIZE \
    --location=/appl/iso/CentOS-8-x86_64-1905-dvd1.iso \
    --console pty,target_type=serial \
    --network bridge=virbr0 \
    --extra-args "console=tty0 console=ttyS0,115200n8"

The script above takes four parameters: hostname, HDD size, memory size, and number of CPUs. Those parameters are then fed into virt-install.

The new bit I'll add is -x option and supply the kickstart file location. Mine is stored on my NFS server. You can store the kickstart file on a USB, HTTP, or FTP server, you're not limited to NFS.

-x 'ks=nfs:nfs1.staging.local:/appl/iso/anaconda-ks.cfg ksdevice=enp1s0'

The ksdevice option isn't necessary if you only have one network interface. However if you have multiple interfaces it maybe wise to enable the specific interface that can connect to the NFS server. In my case it is enp1s0.

The full script is below:

#!/bin/bash

echo " creating VM now  "

echo -n " Enter hostname: "
read HNAME

echo -n " Hard drive size? (In GB): "
read HDSIZE

echo -n " Memory size? (In MB): "
read MEMSIZE

echo -n " Number of CPUs? "
read CPUS

virt-install --name $HNAME \
    --disk path=/appl/images/$HNAME.qcow2,bus=virtio,size=$HDSIZE \
    --graphics=none \
    --os-type=linux \
    --os-variant=centos \
    --vcpu=$CPUS \
    --ram=$MEMSIZE \
    --location=/appl/iso/CentOS-8-x86_64-1905-dvd1.iso \
    --console pty,target_type=serial \
    --network bridge=virbr0 \
    -x 'ks=nfs:nfs1.staging.local:/appl/iso/anaconda-ks.cfg ksdevice=enp1s0' \
    --extra-args "console=tty0 console=ttyS0,115200n8"

All that is left is to kick off the script! Save the file and execute it. Now you can sit back and watch as the installation of CentOS 8.