Skip to content

Kickstart Automated Installation

Kickstart is an automated installation technology provided by Red Hat-based distributions. By pre-defining all installation options in a configuration file (ks.cfg), it enables fully unattended operating system deployment. This guide covers how Kickstart works, the configuration file structure, common directives, generating configs from existing systems, and PXE network boot integration.

Traditional installations require an administrator to manually select options (language, timezone, partitioning, packages, etc.) through the installer UI. Kickstart pre-defines all these options in a text file, and the installer (Anaconda) reads this file to automatically complete the entire installation process.

Key advantages:

  • No human intervention needed, ideal for large-scale batch deployments
  • Configurations can be version-controlled, ensuring consistency
  • Supports custom scripts (pre/post) for automated post-install configuration
  • Can be served via HTTP, FTP, NFS, or local media

Generating a Kickstart File from an Existing Installation

Section titled “Generating a Kickstart File from an Existing Installation”

After each installation, Anaconda automatically generates a Kickstart file recording all options used:

View the auto-generated Kickstart file
cat /root/anaconda-ks.cfg

This file can be used as a template, modified as needed for subsequent installations.

Copy it as a working template
cp /root/anaconda-ks.cfg /root/my-ks.cfg

You can use pykickstart tools to validate your configuration:

Install pykickstart tools
sudo dnf install pykickstart -y
Validate a Kickstart file
ksvalidator /root/my-ks.cfg

A Kickstart configuration file consists of three sections, in order:

  1. Command section — Installation options (required and optional directives)
  2. %packages section — Packages to install
  3. %pre / %post script sections — Scripts to run before and after installation
/root/my-ks.cfg full example
#version=RHEL9
# === Installation source ===
# Network install source
url --url="https://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/"
# Use text-mode installation (no GUI)
text
# Automatically reboot after installation
reboot
# === Basic system settings ===
# Language
lang en_US.UTF-8
# Keyboard layout
keyboard --xlayouts='us'
# Timezone
timezone America/New_York --utc
# === Network configuration ===
network --bootproto=dhcp --device=ens18 --onboot=on --hostname=server01.example.com
# === Security settings ===
# Root password (encrypted format)
rootpw --iscrypted $6$rounds=4096$randomsalt$hashedpasswordhere
# Create a regular user
user --name=admin --groups=wheel --iscrypted --password=$6$rounds=4096$salt$hash
# SELinux mode
selinux --enforcing
# Firewall
firewall --enabled --ssh
# === Disk partitioning ===
# Clear all partitions
clearpart --all --initlabel
# Automatic partitioning scheme
autopart --type=lvm
# Or manual partitioning
# part /boot --fstype=xfs --size=1024
# part /boot/efi --fstype=efi --size=512
# part pv.01 --size=1 --grow
# volgroup vg_sys pv.01
# logvol / --fstype=xfs --name=lv_root --vgname=vg_sys --size=20480
# logvol /var --fstype=xfs --name=lv_var --vgname=vg_sys --size=10240
# logvol swap --name=lv_swap --vgname=vg_sys --size=4096
# Boot loader
bootloader --location=mbr --append="crashkernel=auto"
# === Packages ===
%packages
@^minimal-environment
@standard
vim-enhanced
wget
curl
chrony
bash-completion
%end
# === Post-installation script ===
%post --log=/root/ks-post.log
#!/bin/bash
# Enable common services
systemctl enable chronyd
systemctl enable sshd
# Update the system
dnf update -y
# Configure SSH security options (use a drop-in file instead of relying on
# the default commented lines, which a plain sed may fail to match)
# This example only sets passwords (rootpw / user) and injects no SSH public key,
# so password login MUST stay enabled — otherwise you can't SSH in after first boot.
cat > /etc/ssh/sshd_config.d/00-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication yes
EOF
# Once deployed, inject an SSH public key and set PasswordAuthentication to no
# (switch to key-based auth). If you already write ~/.ssh/authorized_keys via
# %post in this Kickstart, you can set it to no directly.
# Install EPEL repository
dnf install -y epel-release
# Create custom directories
mkdir -p /opt/apps
echo "Post-installation script completed." >> /root/ks-post.log
%end
Network install
url --url="https://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/"
Install from local CD/DVD
cdrom
Install from NFS
nfs --server=192.168.1.100 --dir=/exports/almalinux9
DHCP configuration
network --bootproto=dhcp --device=ens18 --onboot=on
Static IP configuration
network --bootproto=static --device=ens18 --ip=192.168.1.10 --netmask=255.255.255.0 --gateway=192.168.1.1 --nameserver=8.8.8.8,8.8.4.4 --onboot=on
Set hostname
network --hostname=server01.example.com
Automatic partitioning (LVM)
clearpart --all --initlabel
autopart --type=lvm
Automatic partitioning (plain)
clearpart --all --initlabel
autopart --type=plain
Manual partitioning example
clearpart --all --initlabel --drives=sda
part /boot --fstype=xfs --size=1024 --ondisk=sda
part /boot/efi --fstype=efi --size=512 --ondisk=sda
part pv.01 --size=1 --grow --ondisk=sda
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=lv_root --vgname=vg_sys --size=20480
logvol /home --fstype=xfs --name=lv_home --vgname=vg_sys --size=10240
logvol /var --fstype=xfs --name=lv_var --vgname=vg_sys --size=10240
logvol /var/log --fstype=xfs --name=lv_log --vgname=vg_sys --size=5120
logvol swap --name=lv_swap --vgname=vg_sys --size=4096

Passwords in Kickstart should use encrypted format. Generate them with:

Generate an encrypted password
python3 -c 'import crypt; print(crypt.crypt("YourPassword", crypt.mksalt(crypt.METHOD_SHA512)))'

Or using openssl:

Generate encrypted password with openssl
openssl passwd -6
Minimal install with extra packages
%packages
@^minimal-environment
vim-enhanced
wget
curl
net-tools
-iwl*firmware
%end
  • @^minimal-environment — Environment group (minimal installation)
  • @standard — Package group
  • -iwl*firmware — The - prefix excludes the package
post script example
%post --log=/root/ks-post.log
#!/bin/bash
# Configure additional repositories
dnf install -y epel-release
# Install monitoring agent
dnf install -y zabbix-agent
# Configure NTP
sed -i 's/^pool.*iburst/server time.google.com iburst/' /etc/chrony.conf
systemctl enable chronyd
# Disable unnecessary services
systemctl disable postfix
%end
post script — non-chroot environment
%post --nochroot --log=/mnt/sysimage/root/ks-nochroot.log
#!/bin/bash
# Execute in non-chroot environment (can access installation media)
cp /run/install/repo/extras/custom.conf /mnt/sysimage/etc/custom.conf
%end
pre script example (runs before installation)
%pre --log=/tmp/ks-pre.log
#!/bin/bash
# Determine partitioning based on disk size
DISK_SIZE=$(lsblk -dn -o SIZE -b /dev/sda | awk '{print int($1/1024/1024/1024)}')
if [ $DISK_SIZE -gt 500 ]; then
echo "Large disk detected: ${DISK_SIZE}GB"
fi
%end
Install HTTP server and host the Kickstart file
sudo dnf install httpd -y
sudo cp /root/my-ks.cfg /var/www/html/ks.cfg
sudo systemctl start httpd
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

At the installer boot prompt, add the boot parameter:

Installer boot parameter
inst.ks=http://192.168.1.100/ks.cfg
Copy the Kickstart file to a USB drive
sudo mount /dev/sdc1 /mnt
sudo cp /root/my-ks.cfg /mnt/ks.cfg
sudo umount /mnt

Boot parameter:

Read Kickstart from USB
inst.ks=hd:sdc1:/ks.cfg
Read Kickstart from NFS
inst.ks=nfs:192.168.1.100:/exports/ks.cfg

PXE (Preboot eXecution Environment) allows booting and installing over the network. Combined with Kickstart, it enables fully automated network deployment.

  • DHCP server — Assigns IP addresses and points to the TFTP server
  • TFTP server — Serves boot files (pxelinux.0 / GRUB)
  • HTTP/FTP server — Serves the installation source and Kickstart file
Install services required for PXE
sudo dnf install dhcp-server tftp-server syslinux httpd -y
Set up the TFTP directory
sudo mkdir -p /var/lib/tftpboot/pxelinux.cfg
sudo cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/menu.c32 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/ldlinux.c32 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/libutil.c32 /var/lib/tftpboot/
/var/lib/tftpboot/pxelinux.cfg/default example
DEFAULT menu.c32
PROMPT 0
TIMEOUT 100
LABEL almalinux9
MENU LABEL Install AlmaLinux 9
KERNEL vmlinuz
APPEND initrd=initrd.img inst.ks=http://192.168.1.100/ks.cfg

A complete PXE deployment is beyond the scope of this guide. For full details, refer to the official documentation of your distribution.

Before deploying to production, it is strongly recommended to test with a virtual machine:

Test Kickstart installation with virt-install
sudo virt-install \
--name ks-test \
--ram 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/ks-test.qcow2,size=20 \
--location https://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/ \
--initrd-inject=/root/my-ks.cfg \
--extra-args="inst.ks=file:/my-ks.cfg console=ttyS0" \
--nographics
List virtual machines after installation
sudo virsh list --all
Connect to the VM console
sudo virsh console ks-test
Check the post-installation log
cat /root/ks-post.log
Confirm the partition layout
lsblk
Confirm the number of installed packages
rpm -qa | wc -l
  1. Version control your Kickstart files — Use Git to manage all ks.cfg files
  2. Use encrypted passwords — Never store plaintext passwords in ks.cfg
  3. Test in a VM first — Validate every change in a virtual machine before production use
  4. Use ksvalidator to check syntax — Avoid syntax errors that cause installation failures
  5. Leverage %post scripts — Automate post-installation configuration to reduce manual work
  6. Log everything — Use the --log parameter in %post to record execution logs
  7. Modularize configurations — Use %include to incorporate configuration file fragments