Create a bootable ISO with kickstart#
Installing Linux on a physical or virtual machine can be fun for a couple of time, but configuring a system can be combursome after a couple of times. Red Hat developed Kickstart to install and configure machines via the network, but also as part of an ISO file that can used in a virtual CD-ROM drive or on a bootable USB-drive.
Manual procedure#
The following steps are required to create a bootable ISO file with a kickstart file and when the ISO file is booted, the kickstart file is used to install and configure the system. Creating a bootable ISO file is not a difficult task, but it is a manual procedure. The following steps are required to create a bootable ISO file with a kickstart file.
Installing all required packages in Red Hat based systems:
# dnf install epel-release
# dnf install p7zip p7zip-plugins isomd5sum genisoimage
Or installing all required packages in Debian based systems:
# apt install genisoimage isomd5sum p7zip-full
Download NetInstall ISO and validate checksum:
$ curl http://ftp.nluug.nl/ftp/pub/os/Linux/distr/CentOS/7/isos/x86_64/CentOS-7-x86_64-NetInstall-1708.iso --output /tmp/some.iso
$ sha256sum --ignore-missing -c sha256sum.txt
Prepare new directory tree based on ISO:
mkdir /tmp/bootiso /tmp/bootisoks
mount -o loop /tmp/some.iso /tmp/bootiso
cp -r /tmp/bootiso/* /tmp/bootisoks/
umount /tmp/bootiso && rmdir /tmp/bootiso
chmod -R u+w /tmp/bootisoks
Add kickstart file and update configuration for the bootloader:
cp kickstart.cfg /tmp/bootisoks/isolinux/ks.cfg
cp isolinux.cfg /tmp/bootisoks/isolinux/isolinux.cfg
Build ISO image and add MD5 signature:
cd /tmp/bootisoks && mkisofs -o /tmp/boot.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -V "CentOS 7 x86_64" -R -J -v -T isolinux/. .
implantisomd5 /tmp/boot.iso
Remove build directory structure:
cd /tmp && rm -rf /tmp/bootisoks
File boot.iso can now be used by KVM, VMWare, bootable USB, etc. Two files are required to create a bootable ISO file, a kickstart file and a configuration file for the bootloader. The kickstart file is used to install and configure the system and the configuration file for the bootloader is used to boot the system and use the kickstart file. Below is an example of a kickstart file for CentOS 7:
kickstart.ks
##version=DEVEL
auth --enableshadow --passalgo=sha512
cdrom
text
firstboot --enable
ignoredisk --only-use=sda
keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8
network --bootproto=static --device=ens3 --ip=192.168.105.104 --netmask=255.255.255.0 --gateway=192.168.105.1 --ipv6=auto --nameserver=8.8.8.8,8.8.4.4 --activate
network --hostname=server.homelab.example.org
firewall --enabled --ssh
rootpw --lock
timezone Europe/Amsterdam --isUtc
bootloader --location=mbr --boot-drive=sda
autopart --type=lvm
clearpart --all --initlabel
reboot --eject
user --groups=wheel --homedir=/home/sysadmin --name=sysadmin --password=cangetin --plaintext --gecos="System Administration Account"
url --url http://mirror.centos.org/centos/$releasever/os/$basearch/
repo --name=extras --baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
repo --name=epel --baseurl=http://download.fedoraproject.org/pub/epel/$releasever/$basearch/
%packages --excludedocs --nobase
@core --nodefaults
openscap
openscap-scanner
openssh-server
scap-security-guide
yum-cron
-aic94xx-firmware*
-alsa-*
-ivtv*
-iwl*firmware
-libertas*
-kexec-tools
-plymouth*
-postfix
%end
%post --log=/root/ks-post.log
sed -i 's/update_cmd.*/update_cmd=minimal-security/' /etc/yum/yum-cron.conf
sed -i 's/apply_updates.*/apply_updates=yes/' /etc/yum/yum-cron.conf
yum -y update-minimal --security
%end
%addon org_fedora_oscap
content-type = scap-security-guide
profile = standard
%end
%addon com_redhat_kdump --disable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=8 --minquality=50 --strict --nochanges --notempty
pwpolicy user --minlen=8 --minquality=50 --strict --nochanges --notempty
pwpolicy luks --minlen=8 --minquality=50 --strict --nochanges --notempty
%end
The second file is the configuration file for the bootloader, in this case isolinux. The configuration file is used to boot the system and use the kickstart file. Below is an example of a configuration file for isolinux to start the installation process automatically when the ISO is used:
isolinux.cfg
#default vesamenu.c32
timeout 100
display boot.msg
# Clear the screen when exiting the menu, instead of leaving the menu displayed.
# For vesamenu, this means the graphical background is still displayed without
# the menu itself for as long as the screen remains in graphics mode.
menu clear
menu background splash.png
menu title CentOS 7
menu vshift 8
menu rows 18
menu margin 8
#menu hidden
menu helpmsgrow 15
menu tabmsgrow 13
# Border Area
menu color border * #00000000 #00000000 none
# Selected item
menu color sel 0 #ffffffff #00000000 none
# Title bar
menu color title 0 #ff7ba3d0 #00000000 none
# Press [Tab] message
menu color tabmsg 0 #ff3a6496 #00000000 none
# Unselected menu item
menu color unsel 0 #84b8ffff #00000000 none
# Selected hotkey
menu color hotsel 0 #84b8ffff #00000000 none
# Unselected hotkey
menu color hotkey 0 #ffffffff #00000000 none
# Help text
menu color help 0 #ffffffff #00000000 none
# A scrollbar of some type? Not sure.
menu color scrollbar 0 #ffffffff #ff355594 none
# Timeout msg
menu color timeout 0 #ffffffff #00000000 none
menu color timeout_msg 0 #ffffffff #00000000 none
# Command prompt text
menu color cmdmark 0 #84b8ffff #00000000 none
menu color cmdline 0 #ffffffff #00000000 none
# Do not display the actual menu unless the user presses a key. All that is displayed is a timeout message.
menu tabmsg Press Tab for full configuration options on menu items.
menu separator # insert an empty line
menu separator # insert an empty line
label linux
menu label ^Install CentOS 7
menu default
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 inst.ks=cdrom:/ks.cfg
label check
menu label Test this ^media & install CentOS 7
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 rd.live.check quiet
menu separator # insert an empty line
# utilities submenu
menu begin ^Troubleshooting
menu title Troubleshooting
label vesa
menu indent count 5
menu label Install CentOS 7 in ^basic graphics mode
text help
Try this option out if you're having trouble installing
CentOS 7.
endtext
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 xdriver=vesa nomodeset quiet
label rescue
menu indent count 5
menu label ^Rescue a CentOS system
text help
If the system will not boot, this lets you access files
and edit config files to try to get it booting again.
endtext
kernel vmlinuz
append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 rescue quiet
label memtest
menu label Run a ^memory test
text help
If your system is having issues, a problem with your
system's memory may be the cause. Use this utility to
see if the memory is working correctly.
endtext
kernel memtest
menu separator # insert an empty line
label local
menu label Boot from ^local drive
localboot 0xffff
menu separator # insert an empty line
menu separator # insert an empty line
label returntomain
menu label Return to ^main menu
menu exit
menu end
Building an image with GitHub#
The manual procedure above is fine for a one-off build, but if you want to automate this to get the latest ISO, you can use GitHub Actions to build the image for you. The following example will build a new image every time a commit is pushed to the master branch, or a pull request is opened against the master branch. The image will be uploaded as an artifact to the GitHub repository and will be available for download from the Actions tab.
.github/workflows/build.yml
for GitHub Actions#---
name: Build
on:
push:
branches:
- master
pull_request:
branches:
- master
env:
URL: https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.1-x86_64-boot.iso
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Build
run: |
sudo apt install -y genisoimage isomd5sum p7zip-full
curl -L -o /tmp/source.iso ${{ env.URL }}
mkdir bootiso
7z x /tmp/source.iso -o./bootiso
rm -rf bootiso/\[BOOT\]
cp isolinux.cfg bootiso/isolinux/isolinux.cfg
cp kickstart.ks bootiso/isolinux/ks.cfg
cd bootiso
mkisofs -o ../boot.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -V "Custom Boot ISO" -R -J -v -T isolinux/. .
implantisomd5 ../boot.iso
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: boot.iso
path: boot.iso
retention-days: 1
Building an image with GitLab#
Like GitHub Actions, GitLab CI can be used to build an image for you. The following example will build a new image every time a commit is pushed to the master branch, or a pull request is opened against the master branch. The image will be uploaded as an artifact to the GitLab repository and will be available for download from the CI/CD tab.
gitlab-ci.yml
for GitLab CI#---
stages:
- build
variables:
CENTOS: "7.6.1810"
build:
image: centos:${CENTOS}
stage: build
before_script:
- yum install -y epel-release
- yum install -y p7zip p7zip-plugins isomd5sum genisoimage
script:
- curl http://mirror.centos.org/centos/${CENTOS}/os/x86_64/images/boot.iso --output ${CI_PROJECT_DIR}/source.iso
- mkdir ${CI_PROJECT_DIR}/bootiso
- 7z x -o${CI_PROJECT_DIR}/bootiso source.iso
- rm -rf ${CI_PROJECT_DIR}/bootiso/\[BOOT\]
- cp kickstart.ks ${CI_PROJECT_DIR}/bootiso/isolinux/ks.cfg
- cp isolinux.cfg ${CI_PROJECT_DIR}/bootiso/isolinux/isolinux.cfg
- cd ${CI_PROJECT_DIR}/bootiso
- mkisofs -o ${CI_PROJECT_DIR}/boot.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -V "CentOS 7 x86_64" -R -J -v -T isolinux/. .
- implantisomd5 ${CI_PROJECT_DIR}/boot.iso
artifacts:
paths:
- boot.iso
expire_in: 1 day
Customizing Kickstart files#
The example kickstart file provided in this post is a very basic one. It will install a minimal CentOS 7 system with a single user account. You can customize this file to suit your needs. The CentOS documentation has a great guide on how to customize kickstart files and the CentOS/Community-Kickstarts repository has a lot of examples that you can use as a starting point. The examples can be adopted for Red Hat Enterprise Linux, Rocky Linux or Fedora with minimal changes.