Automated Linux installs: Kickstart, preseed and autoinstall

Updated November 2026

An automated install answers every installer question from a text file, so ten or a thousand machines come out identical. Red Hat-style distributions read a Kickstart file, Debian reads a preseed file, and Ubuntu reads an autoinstall YAML file. You put the file on a web server or USB stick and add one option to the installer's kernel command line.

The old KickStart HOWTO (1999) covered Red Hat Linux 5 and boot floppies. The idea is unchanged, but the commands are not. This page uses AlmaLinux 10 as the Red Hat example. The same Kickstart works on RHEL 10 and Rocky Linux 10, and nearly the same file works on Fedora.

Which format your distribution uses (as of November 2026)
DistributionInstallerFileBoot option that loads it
RHEL, AlmaLinux, Rocky 9–10, FedoraAnacondaKickstart (ks.cfg)inst.ks=URL
Debian 13debian-installerpreseed (preseed.cfg)auto url=URL
Ubuntu Server 20.04+, Desktop 23.04+Subiquityautoinstall (user-data or autoinstall.yaml)autoinstall ds=nocloud-net;s=URL/

Kickstart: start from a real install

The easiest first Kickstart file is the one Anaconda writes for you. After any manual install, the installed system has /root/anaconda-ks.cfg with every choice you made. Copy it, edit it, and check it. It contains password hashes, so keep its permissions tight.

Red Hat customers can also use the Kickstart Generator on the Customer Portal, and the Kickstart Converter to update RHEL 9 files for RHEL 10. Both need a portal account.

A complete minimal server Kickstart

This file installs a minimal AlmaLinux 10 server from the public mirror, wipes disk sda, and leaves you with an admin user who logs in with an SSH key. Replace the hash, key and host name with your own.

# ks.cfg – AlmaLinux 10 minimal server (works on RHEL/Rocky 10 with a different url/repo)
text
url --url=https://repo.almalinux.org/almalinux/10/BaseOS/x86_64/os/
repo --name=AppStream --baseurl=https://repo.almalinux.org/almalinux/10/AppStream/x86_64/os/

lang en_US.UTF-8
keyboard --vckeymap=us
timezone America/New_York --utc
timesource --ntp-pool=pool.ntp.org
network --bootproto=dhcp --device=link --activate --hostname=web01.example.com

rootpw --lock
user --name=admin --groups=wheel --iscrypted --password=$6$REPLACE_WITH_HASH
sshkey --username=admin "ssh-ed25519 AAAAC3...REPLACE admin@laptop"

selinux --enforcing
firewall --enabled --ssh

ignoredisk --only-use=sda
zerombr
clearpart --all --initlabel --drives=sda
autopart --type=lvm

%packages
@^minimal-environment
vim-enhanced
%end

%post --log=/root/ks-post.log
dnf -y update
%end

reboot

Make the password hash with openssl passwd -6; it asks for the password and prints a $6$… string (SHA-512 crypt). What the main lines do:

url and repo
Where packages come from. For a RHEL install from the DVD, use cdrom instead.
--device=link
Use the first network card whose link is up, so the same file works on different hardware.
rootpw --lock
Lock the root account; no password is needed with --lock. Members of wheel use sudo.
zerombr, clearpart
Destroy what is on the disk without asking. ignoredisk --only-use=sda keeps other disks (and USB sticks) safe.
autopart --type=lvm
Create the boot, root and swap volumes the platform needs. You cannot combine it with part, reqpart or logvol.
@^minimal-environment
@^ picks an environment group (here "Minimal Install"); @name is a group and a plain name is a package. A leading - removes a package.
%post
A shell script that runs inside the new system (chroot) after installation. Every %packages, %pre and %post section must end with %end.

Check the file before you boot

sudo dnf install pykickstart
ksvalidator -v RHEL10 ks.cfg

No output means the syntax is valid. ksvalidator also fails on deprecated commands, but it does not check what your %pre, %post and %packages sections do. Test in a virtual machine before you point it at real disks.

Old files need editing for RHEL 10. auth/authconfig has been removed (use the authselect command instead), timezone --ntpservers is no longer accepted (use the timesource command), and btrfs and method are gone. vnc is deprecated and no longer has any effect; remote graphical installs use rdp. Run ksvalidator on every RHEL 8 or 9 file before reuse.

Tell the installer where the file is

At the installer's boot menu, press e (GRUB menu) or Tab (older isolinux menus), add one option to the kernel line, and boot (Ctrl+x in GRUB). In a PXE menu, put the option in the configuration file instead:

inst.ks=http://192.168.10.1/ks/web01.cfg       # web server
inst.ks=nfs:192.168.10.1:/exports/ks/web01.cfg  # NFS
inst.ks=hd:UUID=1234-ABCD:/ks.cfg               # a local or USB volume

Without any option, Anaconda also looks for a volume labeled OEMDRV with ks.cfg in its root. Label a USB stick and copy the file to it:

sudo fatlabel /dev/sdX1 OEMDRV        # FAT (or e2label for ext4, xfs_admin -L for XFS)

Before RHEL 7 and Fedora 17 the option was spelled ks=; old guides that use it are out of date.

Debian preseed

Preseeding fills in the answers to debian-installer's questions. Start from the official example for Debian 13 and remove the # from the lines you need:

wget https://www.debian.org/releases/stable/example-preseed.txt -O preseed.cfg

A short working core, for one disk with LVM:

d-i debian-installer/locale string en_US.UTF-8
d-i keyboard-configuration/xkb-keymap select us
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string web02
d-i netcfg/get_domain string example.com
d-i mirror/country string manual
d-i mirror/http/hostname string deb.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i passwd/root-login boolean false
d-i passwd/user-fullname string Admin
d-i passwd/username string admin
d-i passwd/user-password-crypted password $6$REPLACE_WITH_HASH
d-i clock-setup/utc boolean true
d-i time/zone string America/New_York
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string lvm
d-i partman-auto-lvm/guided_size string max
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto/choose_recipe select atomic
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
tasksel tasksel/first multiselect standard, ssh-server
d-i grub-installer/only_debian boolean true
d-i grub-installer/bootdev string default
d-i finish-install/reboot_in_progress note
d-i preseed/late_command string in-target apt-get -y install sudo

Boot the installer and choose Advanced options → Automated install, or type the parameters yourself:

auto url=http://192.168.10.1/d-i/preseed.cfg
# where the "auto" menu entry is missing:
auto=true priority=critical url=http://192.168.10.1/d-i/preseed.cfg

Auto mode delays the language, country and keyboard questions until the network is up, so the file can answer them. You can also put preseed.cfg in the root of the initrd, which works with every install method but means rebuilding the initrd. Preseeding cannot reuse existing partitions: it must partition a whole disk or its free space.

To find the name of a question you did not cover, do one manual install and run debconf-get-selections --installer (from the debconf-utils package) on the result.

Ubuntu autoinstall

Ubuntu's Subiquity installer reads a YAML file. It differs from preseed in one important way: if an autoinstall file is present at all, every question you did not answer takes its default instead of stopping to ask. The most common way to deliver it is as cloud-init user-data:

#cloud-config
autoinstall:
  version: 1
  identity:
    hostname: web03
    username: admin
    password: "$6$REPLACE_WITH_HASH"
  ssh:
    install-server: true
    authorized-keys:
      - ssh-ed25519 AAAAC3...REPLACE admin@laptop
    allow-pw: false
  storage:
    layout:
      name: lvm
  packages:
    - vim
  late-commands:
    - curtin in-target -- apt-get -y upgrade

The first line, #cloud-config, is required. Serve the file next to an empty meta-data file and point the installer at the directory (keep the trailing slash; in a GRUB menu, escape the semicolon as \; because GRUB treats a bare ; as a command separator):

mkdir -p ~/www && cd ~/www      # put user-data here
touch meta-data
python3 -m http.server 3003

# installer kernel command line:
autoinstall ds=nocloud-net\;s=http://192.168.10.1:3003/

Other options: copy autoinstall.yaml (without the #cloud-config wrapper) to the root of the USB stick, next to the casper folder, or build a small seed ISO with cloud-localds seed.iso user-data meta-data from cloud-image-utils. Without the autoinstall keyword on the command line, the installer asks for confirmation before it erases the disk. The lvm layout uses the largest disk unless you add a match: rule.

Network installs with PXE and iPXE

For real automation, boot the installer from the network too. The firmware gets an address and a boot file name from DHCP, downloads a boot loader over TFTP or HTTP, and that boot loader fetches the installer kernel and initrd. iPXE makes this easy because it can load everything over HTTP. With UEFI Secure Boot, use the signed iPXE build from the iPXE releases (ipxe-shim.efi) and the distribution's shim, as described on ipxe.org.

An iPXE script that installs AlmaLinux 10 with the Kickstart above:

#!ipxe
dhcp
set repo https://repo.almalinux.org/almalinux/10/BaseOS/x86_64/os
kernel ${repo}/images/pxeboot/vmlinuz inst.repo=${repo} inst.ks=http://192.168.10.1/ks/web01.cfg
initrd ${repo}/images/pxeboot/initrd.img
shim ${repo}/EFI/BOOT/BOOTX64.EFI
boot

The shim line does nothing when Secure Boot is off, so it is safe to keep. For Debian, use the netboot.tar.gz image from the Debian mirror (under dists/trixie/main/installer-amd64/current/images/netboot/); for Ubuntu, the casper/vmlinuz and casper/initrd files from the live server ISO. DHCP and TFTP setup with dnsmasq is shown in the Diskless HOWTO.

Mistakes to avoid

The classic 1999 KickStart HOWTO is no longer kept on tldp.org. For disk layouts, see the Partition mini-HOWTO.

Sources