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.
What is Kickstart
Section titled “What is Kickstart”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:
cat /root/anaconda-ks.cfgThis file can be used as a template, modified as needed for subsequent installations.
cp /root/anaconda-ks.cfg /root/my-ks.cfgUsing the Kickstart Validator
Section titled “Using the Kickstart Validator”You can use pykickstart tools to validate your configuration:
sudo dnf install pykickstart -yksvalidator /root/my-ks.cfgks.cfg File Structure
Section titled “ks.cfg File Structure”A Kickstart configuration file consists of three sections, in order:
- Command section — Installation options (required and optional directives)
- %packages section — Packages to install
- %pre / %post script sections — Scripts to run before and after installation
Complete Configuration Example
Section titled “Complete Configuration Example”#version=RHEL9
# === Installation source ===# Network install sourceurl --url="https://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/"
# Use text-mode installation (no GUI)text
# Automatically reboot after installationreboot
# === Basic system settings ===# Languagelang en_US.UTF-8
# Keyboard layoutkeyboard --xlayouts='us'
# Timezonetimezone 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 useruser --name=admin --groups=wheel --iscrypted --password=$6$rounds=4096$salt$hash
# SELinux modeselinux --enforcing
# Firewallfirewall --enabled --ssh
# === Disk partitioning ===# Clear all partitionsclearpart --all --initlabel
# Automatic partitioning schemeautopart --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 loaderbootloader --location=mbr --append="crashkernel=auto"
# === Packages ===%packages@^minimal-environment@standardvim-enhancedwgetcurlchronybash-completion%end
# === Post-installation script ===%post --log=/root/ks-post.log#!/bin/bash
# Enable common servicessystemctl enable chronydsystemctl enable sshd
# Update the systemdnf 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 noPasswordAuthentication yesEOF# 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 repositorydnf install -y epel-release
# Create custom directoriesmkdir -p /opt/apps
echo "Post-installation script completed." >> /root/ks-post.log%endCommon Directives Explained
Section titled “Common Directives Explained”Installation Source
Section titled “Installation Source”url --url="https://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/"cdromnfs --server=192.168.1.100 --dir=/exports/almalinux9Network Configuration
Section titled “Network Configuration”network --bootproto=dhcp --device=ens18 --onboot=onnetwork --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=onnetwork --hostname=server01.example.comDisk Partitioning
Section titled “Disk Partitioning”clearpart --all --initlabelautopart --type=lvmclearpart --all --initlabelautopart --type=plainclearpart --all --initlabel --drives=sdapart /boot --fstype=xfs --size=1024 --ondisk=sdapart /boot/efi --fstype=efi --size=512 --ondisk=sdapart pv.01 --size=1 --grow --ondisk=sdavolgroup vg_sys pv.01logvol / --fstype=xfs --name=lv_root --vgname=vg_sys --size=20480logvol /home --fstype=xfs --name=lv_home --vgname=vg_sys --size=10240logvol /var --fstype=xfs --name=lv_var --vgname=vg_sys --size=10240logvol /var/log --fstype=xfs --name=lv_log --vgname=vg_sys --size=5120logvol swap --name=lv_swap --vgname=vg_sys --size=4096Password Generation
Section titled “Password Generation”Passwords in Kickstart should use encrypted format. Generate them with:
python3 -c 'import crypt; print(crypt.crypt("YourPassword", crypt.mksalt(crypt.METHOD_SHA512)))'Or using openssl:
openssl passwd -6%packages Section
Section titled “%packages Section”%packages@^minimal-environmentvim-enhancedwgetcurlnet-tools-iwl*firmware%end@^minimal-environment— Environment group (minimal installation)@standard— Package group-iwl*firmware— The-prefix excludes the package
%post Scripts
Section titled “%post Scripts”%post --log=/root/ks-post.log#!/bin/bash
# Configure additional repositoriesdnf install -y epel-release
# Install monitoring agentdnf install -y zabbix-agent
# Configure NTPsed -i 's/^pool.*iburst/server time.google.com iburst/' /etc/chrony.confsystemctl enable chronyd
# Disable unnecessary servicessystemctl disable postfix
%end%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 Scripts
Section titled “%pre Scripts”%pre --log=/tmp/ks-pre.log#!/bin/bash# Determine partitioning based on disk sizeDISK_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%endUsing the Kickstart File
Section titled “Using the Kickstart File”Serving via HTTP
Section titled “Serving via HTTP”sudo dnf install httpd -ysudo cp /root/my-ks.cfg /var/www/html/ks.cfgsudo systemctl start httpdsudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --reloadAt the installer boot prompt, add the boot parameter:
inst.ks=http://192.168.1.100/ks.cfgServing via USB Drive
Section titled “Serving via USB Drive”sudo mount /dev/sdc1 /mntsudo cp /root/my-ks.cfg /mnt/ks.cfgsudo umount /mntBoot parameter:
inst.ks=hd:sdc1:/ks.cfgServing via NFS
Section titled “Serving via NFS”inst.ks=nfs:192.168.1.100:/exports/ks.cfgPXE Network Boot Installation
Section titled “PXE Network Boot Installation”PXE (Preboot eXecution Environment) allows booting and installing over the network. Combined with Kickstart, it enables fully automated network deployment.
PXE Architecture Components
Section titled “PXE Architecture Components”- 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
sudo dnf install dhcp-server tftp-server syslinux httpd -ysudo mkdir -p /var/lib/tftpboot/pxelinux.cfgsudo 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/DEFAULT menu.c32PROMPT 0TIMEOUT 100
LABEL almalinux9 MENU LABEL Install AlmaLinux 9 KERNEL vmlinuz APPEND initrd=initrd.img inst.ks=http://192.168.1.100/ks.cfgA complete PXE deployment is beyond the scope of this guide. For full details, refer to the official documentation of your distribution.
Testing Kickstart with a Virtual Machine
Section titled “Testing Kickstart with a Virtual Machine”Before deploying to production, it is strongly recommended to test with a virtual machine:
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" \ --nographicssudo virsh list --allsudo virsh console ks-testVerifying the Installation
Section titled “Verifying the Installation”cat /root/ks-post.loglsblkrpm -qa | wc -lBest Practices
Section titled “Best Practices”- Version control your Kickstart files — Use Git to manage all ks.cfg files
- Use encrypted passwords — Never store plaintext passwords in ks.cfg
- Test in a VM first — Validate every change in a virtual machine before production use
- Use ksvalidator to check syntax — Avoid syntax errors that cause installation failures
- Leverage %post scripts — Automate post-installation configuration to reduce manual work
- Log everything — Use the
--logparameter in %post to record execution logs - Modularize configurations — Use
%includeto incorporate configuration file fragments