How to Use Kickstart for Automated Fedora Provisioning

Kickstart lets you automate Fedora installations by providing a pre-written answer file that the installer reads to configure the system without manual input.

You have three laptops to set up for a new project

The first machine took forty-five minutes of clicking through the installer, selecting partitions, and typing passwords. The second one is halfway done when you realize you forgot to enable the firewall. The third machine is waiting, and you are staring at the boot menu with a sinking feeling. You need a way to tell Fedora exactly what to do, once, and have it repeat that process without asking a single question.

Kickstart solves this by replacing the interactive installer with a text file. You write the configuration, boot the machine with a reference to that file, and Anaconda executes the installation automatically. The result is a consistent, repeatable deployment that takes the same amount of time whether you are installing one laptop or fifty servers.

What is actually happening

Kickstart is a plain-text configuration file that answers every prompt the installer would normally display. Anaconda, the Fedora installer, parses this file before it touches the disk. The file defines partitioning schemes, network settings, user accounts, package selections, and scripts to run after the base system is installed.

Think of Kickstart as a macro recorder for system provisioning. You define the sequence of actions once. Anaconda replays that sequence on any target machine. The installer reads the file via a kernel parameter passed at boot. It validates the syntax, applies the directives, and proceeds without user intervention. If a directive is missing or malformed, Anaconda stops and reports an error. The file is usually named ks.cfg and can be hosted on a USB drive, a web server, or embedded directly in the installation media.

Create a Kickstart file

The fastest way to start is to reuse the configuration from a working system. Anaconda saves a copy of the Kickstart file it used during installation in the root home directory. You can copy that file, edit it, and deploy it to other machines.

cp /root/anaconda-ks.cfg ~/my-ks.cfg
# Anaconda writes this file after every install. It contains the exact config used.

Edit the file to match your requirements. A Kickstart file has three main sections. The global section sets options like language, timezone, and network. The %packages section lists what to install. The %post section runs commands after the base system is installed.

Here is a complete example that configures a minimal server with SSH access, automatic partitioning, and a post-install update.

#version=FEDORA-40
# text mode installer. No GUI overhead reduces memory usage.
text
# reboot after installation completes.
reboot

# clear all existing partitions and create a fresh label.
clearpart --all --initlabel
# let anaconda decide the partition layout based on disk size.
autopart

# configure network via DHCP and activate immediately.
network --bootproto=dhcp --activate
# set root password using a pre-computed hash. Never use plaintext.
rootpw --iscrypted $6$rounds=480000$saltsalt$hashhash
# create admin user with sudo access via wheel group.
user --name=admin --groups=wheel --password=$6$rounds=480000$saltsalt$hashhash

lang en_US.UTF-8
keyboard us
timezone America/New_York --utc

%packages
# install the server environment group.
@^server-product-environment
# add net-tools for legacy commands like ifconfig.
net-tools
# exclude packages you do not want.
-excluded-package
%end

%post
# run dnf update to patch the fresh install.
dnf -y update
# enable sshd for remote access.
systemctl enable sshd
# reload firewall to apply any runtime changes.
firewall-cmd --reload
%end

Generate the password hash before writing the file. Plaintext passwords are insecure and will fail validation on strict setups.

python3 -c "import crypt; print(crypt.crypt('changeme123'))"
# crypt module generates a salted hash. Use this output in the rootpw line.

Copy the output and paste it into the rootpw and user lines. Replace --plaintext with --iscrypted.

Validate the file

Kickstart syntax is strict. A typo in a flag can abort the install silently or cause a partitioning error that bricks the disk. Validate the file before you boot.

sudo dnf install pykickstart
# install the validator tool from the official package.
ksvalidator my-ks.cfg
# check syntax against the current anaconda version.

If ksvalidator reports an error, fix the file before proceeding. The validator catches missing sections, invalid flags, and package name errors. It does not check for logical mistakes like conflicting partition directives. You still need to review the file manually.

Boot with the Kickstart file

You need to tell the bootloader where the file lives. Edit the kernel parameters at the boot prompt and append the inst.ks= parameter. The value depends on how you are hosting the file.

For HTTP hosting, serve the file from a web server and reference the URL.

# append this to the linux line in grub or pxelinux.
inst.ks=http://192.168.1.10/ks/my-ks.cfg

For USB installs, embed the file on the boot medium.

# reference the file on the second partition of the USB drive.
inst.ks=hd:sdb2:/my-ks.cfg

For NFS hosting, use the NFS syntax.

# mount the kickstart file from an NFS share.
inst.ks=nfs:192.168.1.10:/exports/ks/my-ks.cfg

The inst.ks parameter is the modern standard. The legacy ks parameter still works but may be removed in future releases. Always use inst.ks.

If you are using PXE boot, add the parameter to the append line in your pxelinux.cfg file. The installer will fetch the file during the early boot phase.

Verify it worked

After the machine reboots, check the logs to confirm the installation followed your configuration. Anaconda preserves the Kickstart file used during installation.

cat /root/anaconda-ks.cfg
# verify the installed system matches your intended config.

Compare the output with your source file. If the files differ, the installer interpreted a flag differently than you expected. Check the package list and partition layout to ensure they match your requirements.

Run journalctl -xe to review the boot logs. Look for errors related to services or network configuration. If a service failed to start, the logs will show the reason.

Check the generated anaconda-ks.cfg on the new machine. If it differs from your source, the installer interpreted a flag differently than you expected.

Common pitfalls and errors

Kickstart files can fail in subtle ways. Here are the most common issues and how to fix them.

If the installer hangs at the partitioning screen, your clearpart directive likely conflicts with existing RAID or LVM metadata. Run lsblk on the target disk before writing the file. Add --drives=sda to clearpart to target specific disks.

If the system boots but you cannot log in, check the rootpw line. A missing --iscrypted flag or a malformed hash will lock you out. Ensure the hash is on a single line and contains no whitespace.

If the %post script fails, the installation still completes. The system will boot, but your post-install configuration will be missing. Check /var/log/anaconda/program.log for script errors. Use set -e in your %post script to abort on errors.

If the network is not available in %post, add --activate to the network directive. The installer will bring up the interface before running post-install scripts.

If you see Error: Kickstart error: The following problem occurred on line 12 of the kickstart file, review line 12. The error message usually points to the exact syntax issue.

If the boot menu is gone, GRUB rescue is your friend, not your enemy. Use the rescue shell to reinstall GRUB.

When to use this vs alternatives

Use Kickstart when you need full control over partitioning, disk encryption, and post-install scripting.

Use cloud images when you are deploying to virtual machines and only need package selection changes.

Use manual installation when you are setting up a single workstation and want to verify every step.

Use system-config-kickstart when you prefer a GUI to generate the initial file structure, then switch to text editing for advanced directives.

Where to go next