A Kickstart installation is an automated method for installing Linux distributions such as Red Hat Enterprise Linux (RHEL), Rocky , AlmaLinux, CentOS, Fedora, or their derivatives. It allows you to predefine installation parameters in a configuration file, making it ideal for deploying systems quickly and consistently without manual intervention.
How Kickstart Works
- Kickstart File:
- A plain text file that contains answers to all questions normally asked by the installation program, such as:
- Disk partitioning
- Software programs to be installed
- Network configuration for the server
- Time zone to be used
- The root user password
- Example filename:
ks.cfg
- A plain text file that contains answers to all questions normally asked by the installation program, such as:
- Installation Process:
- During the installation, the system reads the Kickstart file and performs all the steps specified within it without prompting the user for input.
- Deployment:
- The Kickstart file can be delivered to the target system via:
- A local storage medium (e.g., USB, CD/DVD, or hard drive).
- A network server (e.g., HTTP, FTP, or NFS).
- The Kickstart file can be delivered to the target system via:
Mastering KVM Virtualization - The Ultimate eBook
From home labs to production clouds - master KVM Host management, automating KVM administration using Terraform, Vagrant, and cloud automation. This eBook will enable you to build scalable virtual infrastructure that works whether you're learning at home or deploying enterprise solutions. Get your full copy today
Automate VM installation using Virt-install and kickstart
Let’s consider an example to:
- Install Enterprise Linux OS from ISO image
- Use kickstart to automate OS installation
Step 1: Download OS ISO image (DVD)
Download Enterprise Linux DVD iso. This can be RHEL, CentOS Stream, Rocky Linux, AlmaLinux, Oracle Linux, e.t.c.
In this example we are downloading Rocky Linux DVD iso.
wget https://rocky.mirror.liquidtelecom.com/9/isos/x86_64/Rocky-x86_64-dvd.iso
Move the ISO file to the default storage pool directory.
sudo mv Rocky-x86_64-dvd.iso /var/lib/libvirt/images/Rocky-9-x86_64-dvd.iso
Step 2: Create kickstart installation script
We will begin by creating a new file called ks.cfg
:
vim ks.cfg
The contents populated to the file are as shared below:
# System language
lang en_US.UTF-8
# Keyboard layout
keyboard us
# Network configuration
network --bootproto=dhcp
# Timezone
timezone America/New_York --utc
# Root password (plain text)
rootpw --plaintext StrongRootPassw0rd
# Skip the GUI installation (remove for desktop installs)
skipx
# Run installer in text mode
text
# Clear the Master Boot Record
zerombr
# Partitioning information
bootloader --timeout=1 --location=mbr --append="net.ifnames=0 biosdevname=0"
clearpart --all --initlabel
part /boot --fstype=ext4 --size=512
part swap --size=1024
part / --fstype=xfs --grow --size=1
# Packages
%packages
@core
@base
openssh-server
openssh-clients
vim
bash-completion
sudo
selinux-policy-devel
net-tools
tar
bzip2
bind-utils
policycoreutils-python-utils
python3
python3-libselinux
tar
yum-utils
firewalld
%end
# Automatically reboot after installation and eject media
reboot --eject
# Post-installation script
%post
echo "Installation complete!" > /root/installation-log.txt
%end
Extra options that you can use in Kickstart:
- Using encrypted user password
# Generate encrypted passsword
## Python3
python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
## Python2
python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
For root user:
rootpw --iscrypted <encrypted-password-generated>
- Adding standard user account
# plain text password
user --groups=wheel --name=cloudspinx --plaintext --password=StrongUserPassword --gecos="Cloudspinx User"
# Encrypted password
user --groups=wheel --name=cloudspinx --iscrypted --password=<encrypted-password-generated> --gecos="Cloudspinx User"
- Setting static IP address
network --bootproto=static --ip=192.168.122.100 --gateway=192.168.122.1 --netmask=255.255.255.0 --noipv6 --device=eth0 --nameserver=192.168.122.1,8.8.8.8 --activate
- Setting custom partitions with varying sizes
part / --fstype=ext4 --size=10240
part /var --fstype=ext4 --size=20480
part swap --size=2048
- Using LVM (Logical Volume Manager) with automatic partitioning
zerombr
clearpart --all --initlabel
autopart --type=lvm
- Using LVM (Logical Volume Manager) with custom partitions
# Clear existing partitions and create a new layout
clearpart --all --initlabel
# Create a standard partition for /boot
part /boot --fstype=ext4 --size=1024
# Create PV for LVM that uses the entire remaining disk space
part pv.01 --grow
## Create a new physical volume of 50GB
#part pv.01 --size=50000
# Create a volume group named "vg_root"
volgroup vg_root --pesize=4096 pv.01
# Create logical volumes within the "vg_root" volume group
logvol / --vgname=vg_root --name=lv_root --size=20000 --fstype=ext4
logvol /home --vgname=vg_root --name=lv_home --size=10000 --fstype=ext4
logvol swap --vgname=vg_root --name=lv_swap --size=4096 --fstype=swap
- Boot loader configurations like console and changing network card interfaces naming.
bootloader --timeout 1 --append "console=tty0 console=ttyS0,115200 net.ifnames.prefix=net quiet"
- Sets the state of SELinux on the installed system
# Enforcing
selinux --enforcing
# Permissive
selinux --permissive
# Disabled
selinux --disabled
- Enable / Disable services
# Comma separated list
services --disabled=auditd,cups,smartd,nfslock
services --enabled=sshd,firewalld,tuned
- Set NTP servers
timezone America/New_York --ntpservers=time.google.com,time.windows.com
- VNC installation
To allow the graphical installation to be viewed remotely through VNC. This method is usually preferred over text mode, as there are some size and language limitations in text installations
vnc --host=0.0.0.0 --port=5900 --password=Password01
- Disable IPv6 (Add inside %post and before its %end)
echo "net.ipv6.conf.all.disable_ipv6 = 1" > /etc/sysctl.d/50-ipv6.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.d/50-ipv6.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.d/50-ipv6.conf
sed -i -e '/^::1/d' /etc/hosts
sed -i -e 's,^OPTIONS=",OPTIONS="-4 ,g' -e 's, ",",' /etc/sysconfig/chronyd
sed -Ei -e 's,^(#|)AddressFamily .*,AddressFamily inet,' /etc/ssh/sshd_config
sed -i -e 's,^IPv6_rpfilter=yes,IPv6_rpfilter=no,' /etc/firewalld/firewalld.conf
sed -i -e '/dhcpv6-client/d' /etc/firewalld/zones/public.xml
Step 3: Create VM instance using kickstart and virt-install
Define variables used in the installation:
VM_NAME=rocky9 # Name of VM to create
DISK_SIZE=50 # Create 50GB disk size
MEM_SIZE=2048 # Memory setting in MiB
VCPUS=2 # CPU Cores count
BR_NAME=virbr0 # Bridge network name
OS_VARIANT="rhel9.5" # List using osinfo-query os
INST_GRAPHICS=none # Install graphics: none, vnc, spice
ISO_FILE=/var/lib/libvirt/images/Rocky-9-x86_64-dvd.iso # Path to ISO file
Create a VM instance using virt-install
and kickstart configuration file.
sudo virt-install \
--name $VM_NAME \
--memory=$MEM_SIZE \
--vcpus=$VCPUS \
--location $ISO_FILE \
--disk size=${DISK_SIZE} \
--network bridge=$BR_NAME \
--graphics=$INST_GRAPHICS \
--os-variant=$OS_VARIANT \
--console pty,target_type=serial \
--initrd-inject ks.cfg --extra-args "inst.ks=file:/ks.cfg console=tty0 console=ttyS0,115200n8"
The instalallation process should start and progress automatically.
Starting install...
Retrieving 'vmlinuz' | 0 B 00:00:00 ...
Retrieving 'initrd.img' | 0 B 00:00:00 ...
Allocating 'rocky9.qcow2' | 0 B 00:00:00 ...
WARNING Overriding memory to 3072 MiB needed for rhel9.5 network install.
Creating domain... | 0 B 00:00:00
Running text console command: virsh --connect qemu:///system console rocky9
Connected to domain 'rocky9'
Escape character is ^] (Ctrl + ])
....
Starting installer, one moment...
anaconda 34.25.5.9-1.el9.rocky.0.3 for Rocky Linux 9.5 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
18:17:42 Not asking for VNC because of an automated install
18:17:42 Not asking for VNC because text mode was explicitly asked for in kickstart
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) (Custom software selected)
5) [x] Installation Destination 6) [x] Kdump
(Custom partitioning selected) (Kdump is enabled)
7) [x] Network configuration 8) [ ] User creation
(Connected: enp1s0) (No user will be created)
================================================================================
================================================================================
Progress
.
Setting up the installation environment
Configuring storage
Creating disklabel on /dev/vda
Creating xfs on /dev/vda3
Creating swap on /dev/vda2
Creating ext4 on /dev/vda1
...
Running pre-installation scripts
.
Running pre-installation tasks
....
Installing.
Starting package installation process
================================================================================
================================================================================
After the installation you should get a login page:
Rocky Linux 9.5 (Blue Onyx)
Kernel 5.14.0-503.14.1.el9_5.x86_64 on an x86_64
Activate the web console with: systemctl enable --now cockpit.socket
localhost login:
Login as root user with the password set in the ks.cfg
file.
localhost login: root
Password:
[root@localhost ~]# cat /etc/redhat-release
Rocky Linux release 9.5 (Blue Onyx)
We can check the IP address assignment and disk partitioning scheme after the OS installation is complete.
[root@localhost ~]# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:fa:af:7e brd ff:ff:ff:ff:ff:ff
altname enp1s0
inet 192.168.122.226/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
valid_lft 2765sec preferred_lft 2765sec
inet6 fe80::2a46:dfc0:3ef6:b826/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@localhost ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs tmpfs 888M 0 888M 0% /dev/shm
tmpfs tmpfs 355M 5.1M 350M 2% /run
/dev/vda3 xfs 49G 1.9G 47G 4% /
/dev/vda1 ext4 488M 260M 192M 58% /boot
tmpfs tmpfs 178M 0 178M 0% /run/user/0
More guides from the Cloudspinx team: