How to Build a Custom CentOS ISO with Pre-installed RPMs and Automated Post-install Scripts


2 views

Creating a custom CentOS ISO requires three fundamental components:

  1. Base system packages (minimal install set)
  2. Custom RPMs (your application packages)
  3. Kickstart file for post-install automation

Before starting, ensure you have:

sudo yum install -y createrepo genisoimage isomd5sum syslinux

And at least 20GB free disk space for working files.

Create a working directory structure:

mkdir -p ~/custom-iso/{base,packages,scripts}
cd ~/custom-iso

Mount the original CentOS ISO and copy contents:

sudo mount -o loop /path/to/CentOS-7-x86_64-Minimal-2009.iso /mnt
rsync -av /mnt/ base/
sudo umount /mnt

Place your RPMs in the packages directory and create a local repo:

cp /path/to/your/*.rpm packages/
createrepo -g comps.xml packages/

Sample comps.xml structure:

<comps>
  <group>
    <id>custom-packages</id>
    <name>Custom Application</name>
    <description>My application components</description>
    <default>true</default>
    <uservisible>true</uservisible>
    <packagelist>
      <packagereq type="mandatory">myapp-core</packagereq>
    </packagelist>
  </group>
</comps>

Here's a sample ks.cfg for automated installation:

#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
install
# Use text mode install
text
# Keyboard layouts
keyboard 'us'
# System language
lang en_US.UTF-8
# Network information
network --bootproto=dhcp --device=eth0 --onboot=on
# Root password
rootpw --iscrypted $6$yourhashedpassword
# System timezone
timezone America/New_York
# System bootloader configuration
bootloader --location=mbr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part / --fstype="xfs" --size=10000
part swap --size=1024

%packages --nobase
@core
myapp-core
myapp-config
%end

%post --log=/root/install.log
#!/bin/bash
# VPN Configuration
cat > /etc/openvpn/client.conf <

Edit isolinux.cfg to include your Kickstart file:

label linux
  menu label ^Install CentOS 7 with MyApp
  kernel vmlinuz
  append initrd=initrd.img inst.ks=cdrom:/ks.cfg quiet

Generate the final ISO image:

mkisofs -o custom-centos.iso \
  -b isolinux/isolinux.bin \
  -c isolinux/boot.cat \
  -no-emul-boot \
  -boot-load-size 4 \
  -boot-info-table \
  -RJ \
  -V "CentOS 7 x86_64 Custom" \
  -T \
  -graft-points \
  base/=./base \
  packages/=./packages \
  ks.cfg=./scripts/ks.cfg

Check the ISO integrity and make it bootable:

implantisomd5 custom-centos.iso
isohybrid custom-centos.iso

Use virtualization for testing before physical deployment:

qemu-system-x86_64 -m 2048 -cdrom custom-centos.iso -boot d
  • Include custom systemd services in %post section
  • Embed SSL certificates in the ISO
  • Pre-configure firewalld rules
  • Add custom users with SSH keys

Common issues and solutions:

Issue Solution
Missing dependencies Use repoquery --requires to verify
Kickstart failures Check /root/install.log
Boot problems Verify isolinux configuration

When building custom CentOS installations, we typically need to accomplish three main objectives:

  1. Include custom RPM packages alongside the base system packages
  2. Automate post-install configuration tasks
  3. Maintain a clean installation process that resembles standard CentOS

First, install the necessary tools on your CentOS build machine:

sudo yum install -y createrepo genisoimage isomd5sum syslinux

Create a working directory structure:

mkdir -p ~/custom-iso/{isolinux,Packages,ks}

Mount the original CentOS ISO and copy its contents:

sudo mount -o loop CentOS-7-x86_64-Minimal-2009.iso /mnt
rsync -av /mnt/ ~/custom-iso/
sudo umount /mnt

Place your custom RPMs in the Packages directory:

cp /path/to/your/*.rpm ~/custom-iso/Packages/

Rebuild the repository metadata:

cd ~/custom-iso
createrepo -g comps.xml .

Here's a sample kickstart configuration (ks/ks.cfg) that includes your custom packages and post-install scripts:

#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# System authorization information
auth --enableshadow --passalgo=sha512
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.UTF-8

# Network information
network --bootproto=dhcp --device=eth0 --onboot=on
# Root password
rootpw --iscrypted $6$yourhashedpassword
# System services
services --enabled="chronyd"
# System timezone
timezone America/New_York --isUtc

%packages
@core
your-custom-package
your-vpn-package

%post --nochroot
#!/bin/bash
# Early post script commands here
%end

%post
#!/bin/bash
# Configure VPN
cat > /etc/your-vpn-config.conf <

Edit isolinux/isolinux.cfg to include your kickstart file:

label linux
  menu label ^Install CentOS 7 with Custom Configuration
  kernel vmlinuz
  append initrd=initrd.img inst.stage2=hd:LABEL=CentOS\x207\x20x86_64 inst.ks=cdrom:/ks/ks.cfg quiet

Generate the new ISO image with the following command:

mkisofs -o ~/custom-centos.iso \
  -b isolinux/isolinux.bin \
  -c isolinux/boot.cat \
  -no-emul-boot \
  -boot-load-size 4 \
  -boot-info-table \
  -J -R -V "CentOS 7 x86_64 Custom" \
  ~/custom-iso

Add MD5 checksum to the ISO:

implantisomd5 ~/custom-centos.iso

Always test your custom ISO in a virtual environment before deployment:

qemu-img create -f qcow2 test-vm.qcow2 20G
qemu-system-x86_64 -m 2048 -cdrom ~/custom-centos.iso -hda test-vm.qcow2
  • Package dependencies: Use yum deplist to verify all required dependencies are included
  • Kickstart errors: Check /var/log/anaconda/ logs during installation
  • Boot failures: Verify ISO volume label matches what's specified in isolinux.cfg

For more complex scenarios, consider:

  • Adding custom systemd services in %post section
  • Including configuration files directly in the ISO
  • Implementing firstboot scripts for additional configuration