In this tutorial, we will walk you through the steps of creating KVM virtual machines with Kickstart. If you are working with virtualized workloads, you will realize that creating virtual machines repeatedly is a time consuming task, especially if you are dealing with large scale virtualization. Going over the same installation steps every now and then, installing packages on those virtual machines is cumbersome and can easily lead to inconsistencies. This is where Kickstart can come in to help automate the deployment and save you sometime to do other tasks. Let’s dive into how you can utilize Kickstart to automate Linux Virtual machines creation on KVM.
Table of Contents
Creating KVM Virtual Machines with Kickstart
What is Kickstart?
To begin with, what is Kickstart? Kickstart is a tool created by RedHat to automate deployment of RedHat based OS such as RHEL, CentOS, Fedora and of course other OSes such Ubuntu and the likes, on KVM virtual manager as virtual machines. It provides a method of performing unattended installations of Linux virtual machines through the use Kickstart text file that stores answers to the questions that the installer usually asks as you do the manual installation.
Through the use Kickstart file, you can be able to specify the packages to be installed on the VM, automatic partitioning, user creation, network configuration and other usual VM setup configurations. Using Kickstart is like using a template for deployment as it ensures that the machines are deployed with consistent settings.
Reference for Kickstart Configuration File Options
A whole documentation explaining the various configuration options used in the Kickstart configuration file is available on the Kickstart Documentation page. For any options used above that is not clear to you, refer to the documentation to read more.
Create the Kickstart Configuration File
As already mentioned, Kickstart configuration file is a text file that stores answers to the usual installer questions. The Kickstart file can be passed to either virt-install cli tool or to GUI installer for automating the process.
The are different ways of creating Kickstart configuration file.
Create Kickstart file using Kickstart Generator tool
If you have access to RedHat Customer Portal, then you can utilize their Kickstart generator tool to generate the Kickstart configuration file for the deployment of your specific RHEL OS version on KVM. Once you have the file, you can customize it further to suit your needs.
Use Kickstart file Generated by Anaconda Installation (Recommended)
When you manually deploy a RHEL based OS on KVM, the Anaconda installer records all the answers you provide during installation in a Kickstart configuration file called anaconda-ks.cfg that is usually saved under the root user home directory as /root/anaconda-ks.cfg.
So, if you have deployed RHEL 9 for example, you should have seen such a file on the server.
Here is a sample configuration;
sudo cat /root/anaconda-ks.cfg
#version=DEVEL
# System authorization information
auth --enableshadow --passalgo=sha512
# Use CDROM installation media
cdrom
# Use graphical install
graphical
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=vda
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8
# Network information
network --bootproto=dhcp --device=eth0 --ipv6=auto --activate
network --hostname=localhost.localdomain
repo --name="Server-HighAvailability" --baseurl=file:///run/install/repo/addons/HighAvailability
repo --name="Server-ResilientStorage" --baseurl=file:///run/install/repo/addons/ResilientStorage
# Root password
rootpw --iscrypted $6$XrYFMAXaTG7iyFBZ$EHqNNWerRsqEt9JIpL6oVmEWph2x7TBYUIW2ss59/jPiEIe6Cjthq2zaqXJDY8Fh9K3mbfQGvwnuCjglk3GLS0
# System services
services --enabled="chronyd"
# System timezone
timezone America/New_York --isUtc
user --name=kifarunix --password=$6$sVC9CWRNJxqPoIYu$jEoA8YOO5RThlFKQgNG5se396lMMVIXPwDeY//8imM7QiwL.Xs132HlRn1ex2av/NXCoxf8f5bUycP53k5vsT0 --iscrypted --gecos="kifarunix"
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda
autopart --type=lvm
# Partition clearing information
clearpart --none --initlabel
%packages
@^minimal
@core
chrony
kexec-tools
%end
%addon com_redhat_kdump --enable --reserve-mb='auto'
%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
For all the options used, counter check them from the reference documentation in the link given above. Some of the have deprecated and will no longer be supported already or in the future versions.
To give a brief explanation of the Kickstart configuration file above;
Version Declaration
#version=DEVEL
:
- Indicates the version of the installer or Kickstart syntax being used.
DEVEL
is used for development/testing purposes.
Authorization
auth --enableshadow --passalgo=sha512
- Enables shadow passwords (more secure password storage).
- Specifies SHA-512 as the password hashing algorithm.
- This options is deprecated.
Installation Source
cdrom
- Specifies the installation source as the CD/DVD media.
Installation Mode
graphical
- Indicates a graphical installation interface.
First Boot Configuration
firstboot --enable
- Enables the first-boot setup wizard after the system is installed.
Disk Configuration
ignoredisk --only-use=vda
- Ignores all disks except for the virtual disk
vda
during installation.
Keyboard and Language
keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8
- Keyboard layout is set to US.
- Language is set to US English.
Networking
network --bootproto=dhcp --device=eth0 --ipv6=auto --activate
network --hostname=localhost.localdomain
- Configures
eth0
to use DHCP for IPv4 and automatically configure IPv6. - Sets the hostname to
localhost.localdomain
.
Repositories
repo --name="Server-HighAvailability" --baseurl=file:///run/install/repo/addons/HighAvailability
repo --name="Server-ResilientStorage" --baseurl=file:///run/install/repo/addons/ResilientStorage
- Adds local repositories for High Availability and Resilient Storage.
Root Password
rootpw --iscrypted $6$XrYFMAXaTG7iyFBZ$EHqNNWerRsqEt9JIpL6oVmEWph2x7TBYUIW2ss59/jPiEIe6Cjthq2zaqXJDY8Fh9K3mbfQGvwnuCjglk3GLS0
- Sets the root password using a hashed value.
- You can use tools such as mkpasswd to generate such a password.
- mkpasswd –method=sha512crypt (will ask you to enter the password)
- If you want to allow remote root logins via ssh using only the password, add the
--allow-ssh
option.
System Services
services --enabled="chronyd"
- Enables the
chronyd
service for time synchronization.
System Timezone
timezone America/New_York --isUtc
- Sets the system timezone to America/New_York and configures it to use UTC.
--isUtc
is deprecated as from RHEL 8
User Configuration
user --name=kifarunix --password=$6$sVC9CWRNJxqPoIYu$jEoA8YOO5RThlFKQgNG5se396lMMVIXPwDeY//8imM7QiwL.Xs132HlRn1ex2av/NXCoxf8f5bUycP53k5vsT0 --iscrypted --gecos="kifarunix"
- Creates a user named
kifarunix
with a hashed password and full name. Similar
Bootloader Configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda
- Configures the bootloader to append
crashkernel=auto
, installs it to the MBR, and sets the boot drive tovda
.
Partitioning
autopart --type=lvm
- Automatically partitions the disk using LVM.
Partition Clearing
clearpart --none --initlabel
- Clears existing partitions without initializing a new partition table.
Package Selection
%packages
@^minimal
@core
chrony
kexec-tools
%end
- Installs minimal and core package groups, along with additional specified packages.
Kdump Configuration
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
- Enables kdump and reserves memory automatically.
Password Policies
%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
- Sets password policies for root, user, and LUKS encrypted volumes passwords.
- All this %anaconda section is deprecated.
Create Kickstart Configuration File Manually
If you are a pro, of course you can create your own Kickstart configuration file. However, manual creation process is prone to mistakes. Be sure to find a way to validate your Kickstart configuration file. You can use ksvalidator commands provided by pykickstart package on RHEL systems. See below.
Validate Kickstart Configuration file
To ensure that the syntax of the Kickstart configuration file is correct and that the file does not include deprecated options, use ksvalidator command against the file. Kindly note that the validator does not attempt to validate the %pre
, %post
and %packages
sections of the Kickstart file. So be sure to check those sections manually. Similarly, it is good to note that validating the syntax of the Kickstart file does not guarantee successful installation!
Install Kickstart Validator Commands on RHEL/CentOS
If you are on RHEL/CentOS or similar OSes, you can install the pykickstart package;
sudo yum install pykickstart
This provides the ksvalidator command that you can now use;
ksvalidator --help
usage: ksvalidator [options] ksfile [ksfile...]
positional arguments:
ksfile filename or URL to read from
options:
-e, --firsterror halt after the first error or warning
-i, --followincludes parse include files when %include is seen
-l, --listversions list the available versions of kickstart syntax
-v VERSION, --version VERSION
version of kickstart syntax to validate against
-h, --help show this help message and exit
For example;
ksvalidator -v RHEL9 ~/rhel-ks.cfg
Sample output;
Checking kickstart file /home/kifarunix/rhel-ks.cfg
The following problem occurred on line 1 of the kickstart file:
auth has been removed.
Ignoring deprecated option on line 19: The --isUtc option has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please mod
ify your kickstart file to remove this option.
You can fix any identified issue and revalidate the configuration file.
Install Kickstart Validator Command on Ubuntu/Debian
Unfortunately, pykickstart
is not available in the default Ubuntu repositories, so you need to install it via pip in a virtual environment.
Install Python and Virtual Environment Tools
sudo apt update
sudo apt install python3 python3-pip python3-venv -y
Create a new directory for your virtual environment and activate it:
mkdir ksvalidator_env
cd ksvalidator_env
python3 -m venv venv
source venv/bin/activate
Use pip to install the pykickstart
package inside the virtual environment:
pip install pykickstart
Run ksvalidator
to check your kickstart file:
ksvalidator /path/to/rhel-ks.cfg
Making Kickstart Available for Installation
Once your Kickstart is ready, you can make it available for the various types of installation, be it network-based or local installation.
Some of the network-based installation methods you can explore include:
- use of HTTP(S) server to serve Kickstart file
- use of NFS shares
- use of FTP/TFTP servers
For local installation, you can make Kickstart available on the local system from where you launch the installation.
Creating RHEL 9 Virtual Machine with Kickstart on KVM
To demonstrate how to use Kickstart file to automate the installation of Virtual machines on KVM, let’s create a RHEL 9 virtual machine.
Prepare Kickstart Configuration file
Here is our sample Kickstart configuration file.
cat /home/kifarunix/rhel-ks.cfg
authselect select sssd --password-hashing=sha512
cdrom
text
firstboot --enable
ignoredisk --only-use=vda
keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8
network --bootproto=dhcp --device=eth0 --ipv6=auto --activate
network --hostname=rhel9.kifarunix.com
#repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream
#repo --name="BaseOS" --baseurl=file:///run/install/sources/mount-0000-cdrom/BaseOS
#repo --name="Server-HighAvailability" --baseurl=file:///run/install/repo/addons/HighAvailability
#repo --name="Server-ResilientStorage" --baseurl=file:///run/install/repo/addons/ResilientStorage
rootpw --iscrypted $6$XrYFMAXaTG7iyFBZ$EHqNNWerRsqEt9JIpL6oVmEWph2x7TBYUIW2ss59/jPiEIe6Cjthq2zaqXJDY8Fh9K3mbfQGvwnuCjglk3GLS0 --allow-ssh
services --enabled="chronyd"
timezone America/New_York
user --name=kifarunix --password=$6$sVC9CWRNJxqPoIYu$jEoA8YOO5RThlFKQgNG5se396lMMVIXPwDeY//8imM7QiwL.Xs132HlRn1ex2av/NXCoxf8f5bUycP53k5vsT0 --iscrypted --gecos="kifarunix" --groups wheel
bootloader --append=" net.ifnames=0 biosdevname=0 crashkernel=auto" --location=mbr --boot-drive=vda
autopart --type=lvm
clearpart --none --initlabel
%packages
@^minimal-environment
@core
chrony
kexec-tools
container-tools
nfs-utils
autofs
vim
cloud-init
cloud-utils-growpart
%end
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%post --nochroot
rsync -avP /run/install/repo/{AppStream,BaseOS} /mnt/sysimage/mnt/
%end
%post
cat > /etc/yum.repos.d/local.repo << 'EOL'
[AppStream]
name = AppStream
baseurl = file:///mnt/AppStream
gpgcheck = 0
enabled = 1
[BaseOS]
name = BaseOS
baseurl = file:///mnt/BaseOS
gpgcheck = 0
enabled = 1
EOL
%end
There are a few things that I have introduced in my Kickstart configuration file to deploying RHEL 9.4 on KVM;
- commented out all repo lines
- Force the naming of the network interfaces into the traditional way of ethX for predictability; bootloader --append=" net.ifnames=0 biosdevname=0 crashkernel=auto" --location=mbr --boot-drive=vda
- Copied the repositories from the installation media and created custom repos, see the %post section (If you want, you can enable your subscriptions to enable some repos).
Validate the file;
ksvalidator ~/rhel-ks.cfg
Looks good;
Checking kickstart file /home/kifarunix/rhel-ks.cfg
Start Kickstart installation
You can start Kickstart installation either by editing the boot options during PXE boot installation or by providing a path to the local Kickstart file. In this guide, we will run the installation via the Virt Manager/virt-install.
Before you can proceed, you need to have the installation ISO medium already. We are using RHEL 9.4 ISO file located under ~/Downloads/rhel-9.4-x86_64-dvd.iso.
To deploy the VM with virt-install and Kickstart file;
sudo virt-install \
--name rhel9.4-server \
--ram 2048 \
--vcpus 2 \
--disk path=/mnt/vol01/kvm/images/rhel9.4-server.qcow2,format=qcow2,size=20 \
--network network=default \
--location /home/kifarunix/Downloads/rhel-9.4-x86_64-dvd.iso \
--graphics none \
--initrd-inject=/home/kifarunix/rhel-ks.cfg \
--extra-args "inst.ks=file:/rhel-ks.cfg console=tty0 console=ttyS0,115200n8"
Ensure the name of the Kickstart file used in the --initrd-inject
option matches the one specified on the extra arguments line.
If all goes well, this should create the virtual machine and begin installation automatically.
This is a snippet of the beginning and towards to the end of installation:
Starting installer, one moment...
anaconda 34.25.4.9-1.el9_4 for Red Hat Enterprise Linux 9.4 started.
* installation log files are stored in /tmp during the installation
* shell is available on TTY2
* if the graphical installation interface fails to start, try again with the
inst.text bootoption to start text installation
* when reporting a bug add logs from /tmp as separate text/plain attachments
15:44:41 Not asking for VNC because of an automated install
15:44:41 Not asking for VNC because text mode was explicitly asked for in kickstart
15:44:41 Not asking for VNC because we don't have a network
Starting automated install.Saving storage configuration...
.Checking storage configuration...
.
....
================================================================================
================================================================================
Installation
1) [x] Language settings 2) [x] Time settings
(English (United States)) (America/New_York timezone)
3) [x] Installation source 4) [x] Software selection
(Local media) (Minimal Install)
5) [x] Installation Destination 6) [x] Kdump
(Automatic partitioning (Kdump is enabled)
selected)
7) [x] Network configuration
(Unknown)
================================================================================
================================================================================
Progress
.
Setting up the installation environment
Configuring storage
Creating disklabel on /dev/vda
Creating xfs on /dev/vda1
Creating lvmpv on /dev/vda2
Creating swap on /dev/mapper/rhel_rhel9-swap
Creating xfs on /dev/mapper/rhel_rhel9-root
...
Running pre-installation scripts
.
Running pre-installation tasks
....
Installing.
Starting package installation process
Downloading packages
...
.
Configuring Red Hat subscription
....
Configuring installed system
..............
Writing network configuration
.
Creating users
.....
Configuring addons
.
Generating initramfs
....
Storing configuration files and kickstarts
.
Running post-installation scripts
.
Installation complete
Use of this product is subject to the license agreement found at:
/usr/share/redhat-release/EULA
Installation complete. Press ENTER to quit:
[anaconda]1:main* 2:shell 3:log 4:storage-log >Switch tab: Alt+Tab | Help: F1
You can press Enter to reboot the Virtual machine. The installer connects to the VM via console.
Verify VM installation
Login with the user credentials specified in the Kickstart;
Red Hat Enterprise Linux 9.4 (Plow)
Kernel 5.14.0-427.13.1.el9_4.x86_64 on an x86_64
rhel9 login: kifarunix
Password:
[kifarunix@rhel9 ~]$ id
uid=1000(kifarunix) gid=1000(kifarunix) groups=1000(kifarunix),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[kifarunix@rhel9 ~]$ hostnamectl
Static hostname: rhel9.kifarunix.com
Icon name: computer-vm
Chassis: vm 🖴
Machine ID: ea77cb4a665648b093aa6369e5675505
Boot ID: 3826016f1c24493ebfb54339dcc0b4d9
Virtualization: kvm
Operating System: Red Hat Enterprise Linux 9.4 (Plow)
CPE OS Name: cpe:/o:redhat:enterprise_linux:9::baseos
Kernel: Linux 5.14.0-427.13.1.el9_4.x86_64
Architecture: x86-64
Hardware Vendor: QEMU
Hardware Model: Standard PC _Q35 + ICH9, 2009_
Firmware Version: 1.16.2-debian-1.16.2-1
[kifarunix@rhel9 ~]$ dnf repolist
Not root, Subscription Management repositories not updated
repo id repo name
AppStream AppStream
BaseOS BaseOS
[kifarunix@rhel9 ~]$ ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:5e:44:c6 brd ff:ff:ff:ff:ff:ff
altname enp1s0
inet 192.168.122.54/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
valid_lft 3511sec preferred_lft 3511sec
inet6 fe80::b515:b22:e552:1edf/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[kifarunix@rhel9 ~]$
Conclusion
By following the steps outlined in this guide, you can successfully deploy a VM on KVM automatically through Kickstart. Once you have the virtual machine running, you can now use the image to provision other vms for for your various workloads. You can see how Terraform can you provision multiple KVM virtual machines automatically. Check the guide below;