Create custom Centos 7 Kickstart boot CD iso

Scenario: You want to create a custom CentOS 7 / RHEL 7 boot CD with custom kickstart files located on the CD. Furthermore you want to perform some post installation tasks like running some Puppet manifests. In this post I describe the process based on CentOS 7.1.

1) Install a base CentOS 7.1 virtual machine

First you need to install your build environment. It is sufficient to install a “@Base” system.

2) Prepare your build environment

If the installation of your CentOS 7.1 virtual machine is finished you can continue with preparing your build environment.

2.1 Create needed folder structure as root

mkdir -p ~/kickstart_build/isolinux/{images,ks,LiveOS,Packages,postinstall}

The folders will contain the following:

  • images: contents of the images directory located on the CentOS DVD
  • ks: all your kickstart files which we will create later on
  • LiveOS: contents of the LieveOS directory on the CentOS DVD
  • Packages: all RPM packages from CentOS 7 DVD plus additional packages. In my case I will also install Puppet agent. Therefore I need some packages from Puppet Labs
  • postinstall: everything you want so to do after installation, for example executing custom scripts or in my case Puppet modules.

2.2 Copy needed content

Now you need to copy all needed content from the CentOS DVD to your local folders. Please save the CentOS 7 ISO file in /tmp and mount it somewhere.

mkdir -p /mnt/iso
mount -o loop /tmp/CentOS-7-x86_64-DVD-1503-01.iso /mnt/iso
cp /mnt/iso/.discinfo ~/kickstart_build/isolinux/
cp /mnt/iso/isolinux/* ~/kickstart_build/isolinux/
rsync -av /mnt/iso/images/ ~/kickstart_build/isolinux/images/
cp /mnt/iso/LiveOS/* ~/kickstart_build/isolinux/LiveOS/
ll /mnt/iso/repodata/ | grep -i comps
-rw-r--r--. 1 root root 157580 1. Apr 01:43 0e6e90965f55146ba5025ea450f822d1bb0267d0299ef64dd4365825e6bad995-c7-x86_64-comps.xml.gz

cp /mnt/iso/repodata/0e6e90965f55146ba5025ea450f822d1bb0267d0299ef64dd4365825e6bad995-c7-x86_64-comps.xml.gz ~/kickstart_build/

cd ~/kickstart_build/
gunzip 0e6e90965f55146ba5025ea450f822d1bb0267d0299ef64dd4365825e6bad995-c7-x86_64-comps.xml
mv 0e6e90965f55146ba5025ea450f822d1bb0267d0299ef64dd4365825e6bad995-c7-x86_64-comps.xml comps.xml

2.3 Get additional packages if needed

As I already mentioned I will also install Puppet Opensource client on my machines to install and configure my machines as needed. So I need to implement additional packages on the custom boot ISO to be able to install and run Puppet manifests.

mkdir /tmp/packages
cd /tmp/packages
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libselinux-ruby-2.2.2-6.el7.x86_64.rpm
wget -e robots=off --mirror --no-parent --no-host-directories --cut-dirs=4 http://yum.puppetlabs.com/el/7/products/x86_64/
wget -e robots=off --mirror --no-parent --no-host-directories --cut-dirs=4 http://yum.puppetlabs.com/el/7/dependencies/x86_64/
rm -Rf index* repodata

2.4 Copy all your packages and create repodata

Now it`s time to bring the CentOS packages and your additional needed packages together. First copy all packages from CentOS 7 ISO to your local folder. Afterwards you can move all additional packages from /tmp/packages to your kickstart packages folder:

rsync -av /mnt/iso/Packages/ ~/kickstart_build/isolinux/Packages/
rsync -av /tmp/packages/ ~/kickstart_build/isolinux/Packages/

Now we need to create the repodata folder in ~/kickstart_build/isolinux/Packages/:

yum install -y createrepo
cd ~/kickstart_build/isolinux
createrepo -g ~/kickstart_build/comps.xml .

3) Prepare Kickstart file

3.1 Create a kickstart

You need to create the kickstart file in ~/kickstart_build/isolinux/ks and name it for example ks.cfg. The content can look like this:

#version=RHEL7
# System authorization information
auth --enableshadow --passalgo=sha512

# Use CDROM installation media
cdrom
# Use text install
install
text
# Run the Setup Agent on first boot
firstboot --disable
#ignoredisk --only-use=sda
# Keyboard layouts
keyboard --vckeymap=de-nodeadkeys --xlayouts='de (nodeadkeys)'
# System language
lang de_DE.UTF-8

# Network information
network --bootproto=static --device=ens3 --noipv6 --activate --ip=192.168.100.2 --netmask=255.255.255.0 --gateway=192.168.100.1 --nameserver=192.168.100.1 --hostname=infrastructure.reimer.local
network --bootproto=static --device=ens9 --noipv6 --activate --ip=10.10.100.2 --netmask=255.255.255.0
# Root password
rootpw --iscrypted "some-crypted-password"
# System timezone
timezone Europe/Berlin --isUtc
# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=sda
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part /boot --fstype="xfs" --size=512
part pv.219 --fstype="lvmpv" --size 1 --grow
volgroup vg_system --pesize=4096 pv.219
logvol / --fstype="xfs" --size=1 --grow --label="rootlv" --name=rootlv --vgname=vg_system
logvol swap --fstype="swap" --size=2048 --name=swaplv --vgname=vg_system

reboot

%packages
@core
@Base
kexec-tools
git
mc
screen
puppet
tree
%end

You can validate your kickstart file like this:

ksvalidator ~/kickstart_build/isolinux/ks/ks.cfg

To create a crypted root password which you can use within your kickstart file do the following:

python -c 'import crypt; print(crypt.crypt("My Password", "$6$My Salt"))'

This generates a SHA512 crypted password.

3.2 Create kickstart postinstallation section

If you want to perform some postinstallation tasks within your kickstart installation you can add an appropriate section in the kickstart file. In my case I want to perform my Puppet configuration during the kickstart installation.

HINT: Be careful. In this case the first step will be the copy of the Puppet manifests from the ISO from which you boot your machine you want to kickstart. This action takes place in the NON-CHROOTED environment. The second step will be the Puppet run itself. This takes place in the CHROOTED environment.

Add the following at the end of your kickstart file:

# Copy needed Puppet files to /root/postinstall
%post --nochroot
#!/bin/sh

set -x -v
exec 1>/mnt/sysimage/root/kickstart-stage1.log 2>&1

echo "==> copying files from media to install drive..."
cp -r /run/install/repo/postinstall /mnt/sysimage/root

%end

%post
#!/bin/sh

set -x -v
exec 1>/root/kickstart-stage2.log 2>&1

ls -l /root/postinstall
puppet apply -l /root/puppetrun.log /root/postinstall/puppet/manifests/site.pp --modulepath=/root/postinstall/puppet/modules/ $*

%end

4) Time for action: create your custom CentOS 7 ISO file and test it

yum install -y genisoimage
cd ~/kickstart_build/
mkisofs -o centos-7-custom.iso -b isolinux.bin -c boot.cat -no-emul-boot -V 'CentOS 7 x86_64' -boot-load-size 4 -boot-info-table -R -J -v -T isolinux/

Now start a new virtual machine from your custom CentOS 7 ISO file and insert the following option at kernel boot:

linux inst.ks=cdrom:/dev/cdrom:/ks/ks.cfg

Congratulations 🙂 Your kickstart installation should run.

14 thoughts on “Create custom Centos 7 Kickstart boot CD iso”

  1. Thanks a bunch man I spent 14 hours figuring how to add rpms to ISO, I was executing “createrepo” from withing the Packages directory and my installation was failing. Thanks to this guide I have been able to run it smoothly.

    PS: Although I get a yum.sqlite.sack error on console but the installation goes on and all the packages are installed.

    1. Hi Asad, thank you for your feedback. Good to know that this solution also works for you. At which point does this error occur?

  2. Fantastic instructions! – one snag:

    I had to dig into a couple of problems that I ran into during boot. One was solved by just starting again from scratch, so I don’t know what that was all about.

    The second problem, was that the CentOS installer is configured to perform a media check before it starts doing anything. This media check was failing because no checksum was found “in the ISO” (I presume in some application data field in the disc image’s headers).

    This checking can be simulated using checkisomd5, which is installed as part of the livecd-tools software package. The package also includes implantisomd5, which is used to add the checksum data to the ISO.

    Example:

    # Implant your ISO with the checksum:
    implantisomd5 my.iso

    Once I performed the above step, the ISO actually booted into the installer, but ks.cfg seems to not have been executed. So begins the next challenge.

    1. For those stumbling onto this in the future, it’s an easy fix:

      Before making the CD, edit the file “~/kickstart_build/isolinux/isolinux.cfg”:
      find the part in the file that starts with “label linux”
      change the text:
      ” append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet”
      to:
      ” append initrd=initrd.img ks=cdrom:/ks.cfg inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 quiet”

      Now it’ll autoboot to that KS too.

  3. Thank you. I have learnt the how to create kickstart..

    I have followed the same instruction and create the ISO image and started with creating the VM in VMware ESXi .

    I have mounted the ISO to CDROM and started the installation.

    Mounting Configuration Files Systems say`s OK
    Started Show Plymouth Boot Screen OK
    Reached target Paths OK
    Reached target Basic System OK
    Hangs on [sda] Assuming drive cache : write through

    Unable to proceed.

    Could you please let me know anything i am missing.

    1. Hi Lokesh,

      please send me the partitioning part of your Kickstart file. And are you using the latest CentOS / RHEL 7 Iso image? Do you want to encrypt your system?

  4. Hi Freimer ,

    Thanks for your reply.

    Yes i am using latest CenOS 7 ISO image and created the custom image as per your information provided above.

    Yes i would like to encrypt the system. Also i need to run the post script to install docker and run the image.

    Please find the kickstart file details below.

    #platform=x86, AMD64, or Intel EM64T
    #version=CentOS
    # Install OS instead of upgrade
    install
    # Keyboard layouts
    keyboard ‘us’
    # Root password
    rootpw –iscrypted $1$kCt0WDca$FevQit.k6hEWHdX341D2c.
    # System timezone
    timezone Asia/Colombo
    # System language
    lang en_US
    # Firewall configuration
    firewall –enabled –http –ssh
    # System authorization information
    auth –useshadow –passalgo=sha512
    # Use CDROM installation media
    cdrom
    # Use graphical install
    graphical
    firstboot –disable
    # SELinux configuration
    selinux –enforcing

    #user Configuration
    user –name ram

    # Network information
    network –bootproto=static –device=eth0 –gateway=192.168.27.72 –ip=192.168.20.32 –nameserver=192.168.30.50 –netmask=255.255.240.0
    # Reboot after installation
    reboot
    # System bootloader configuration
    bootloader –location=mbr
    # Partition clearing information
    clearpart –all
    # Disk partitioning information
    part /boot –fstype=”xfs” –size=500
    part / –fstype=”xfs” –size=10240
    part swap –fstype=”swap” –size=2048

    %post
    useradd lokesh -c “Lokesh Krishnakumar”
    echo redhat | passwd –stdin lokesh
    %end

    %packages
    @^minimal
    @core
    @Base
    kexec-tools
    git
    mc
    screen
    @java
    tree

    %end

    1. Hi Lokesh,

      please put the device definition into your partitioning section in the Kickstart file like:

      zerombr
      clearpart –all –drives=sda,sdb,sdc –initlabel

      part /boot –fstype=xfs –asprimary –ondisk=sda –size=1000
      part pv.001 –asprimary –size=1 –ondisk=sdb –grow
      part pv.002 –asprimary –size=1 –ondisk=sdc –grow

      volgroup vg_system –pesize=4096 pv.001
      volgroup vg_data –pesize=4096 pv.002
      logvol swap –fstype=swap –name=swaplv –vgname=vg_system –size=4096
      logvol / –fstype=xfs –name=rootlv –vgname=vg_system –size=2048 –fsoptions=”inode64,noatime,nodiratime,nobarrier”
      logvol /tmp –fstype=xfs –name=tmplv –vgname=vg_system –size=3072 –fsoptions=”inode64,noatime,nodiratime,nobarrier”
      logvol /usr –fstype=xfs –name=usrlv –vgname=vg_system –size=2048 –fsoptions=”inode64,noatime,nodiratime,nobarrier”
      #[…]

  5. Hello,
    Same procedure holds good for RHEL7 custom iso.?
    Please let me know. I’m facing few issues.

    1. Hi,

      unfortunately I did not find the time to test it with RHEL 7. Should work the same. I`m currently deploying machines only with Red Hat Satellite 6 (Katello is the upstream project).

  6. is there a way to make a minimal installation cd with an especific kernel, i mean i need to create vms with packer using an especific version of the kernel, thank you

    1. Hi Sukrant,

      instead of complaining it would be much more appreciated if you would contribute a beter solution. The article is based on CentOS 7.1. Now we are at 7.4. Maybe things are working now different. But the article should give you a rough overview of what you need to consider if you want to work on your own solution.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.