Building a custom CentOS 6 kickstart disc, part 4

Note: this series of articles applies to CentOS 6; for CentOS 5, see this series.

Let’s make things really interesting with a postinstall script to do some custom configuration.

The good news

In CentOS 5, you had to do some fairly ugly modifications to the boot images to allow your postinstall code to access files from the install media, and then your postinstall code had to remount the install media.  You don’t have to do that anymore!  You can just access your files under /mnt/source.

The %post section

In your kickstart configuration file, you can have sections of commands that are designated to run after the anaconda installer has done its work. These sections are denoted with the %post directive.

Typically, you follow this directive with the bash shebang line and the contents of a custom shell script. One thing to note is the filesystem organization at this point during the installation. Your new system’s disk is mounted at /mnt/sysimage, not at / the way it will be once the system is up and running after installation.

By default, the commands in the %post section are run in a chroot environment, where /mnt/sysimage appears as the / directory. This lets you use “normal” paths to configuration files like /etc instead of /mnt/sysimage/etc (if you didn’t chroot like this, you wouldn’t be able to do things like install RPMs). The primary disadvantage is that your install media is not visible in a chrooted environment.

We solve this problem by building our postinstall in two stages. In the first stage, we tell anaconda not to chroot us; we then copy files from the CD to the hard drive.

In our case, we’ve put all our postinstallation files into the postinstall directory under the ~/kickstart_build/isolinux directory. Note that the isolinux directory in our build environment becomes the root of the install disc that we create. So the contents of the postinstall directory on the install disc are copied to /root/postinstall on the new system’s hard drive.

We’re now ready to run stage 2 of the postinstall, where we actually use the postinstallation files.

Note that in both the stage1 and stage2 postinstall scripts, I redirect stdout to a log file in root’s home directory. This is very helpful for diagnosing problems during the kickstart postinstall. This comes in handy when you have many hundreds of lines of postinstall that need to be tested and debugged.

The sky is the limit for what you can do in the postinstallation:

  • add users or groups
  • install non-CentOS applications from RPMs (see below for some good repos)
  • install non-CentOS applications from tarballs (I prefer RPMs where available, but sometimes you don’t have them handy)
  • set the runlevels for various system services
  • configure servers like apache, samba, sshd, and MySQL
  • configure the default behavior of the bash shell

and anything else you could imagine. In my ideal world, my machines are ready to perform their designated tasks from the very first second I boot them up. I don’t want to have a series of manual steps to complete the configuration.

Organizing the postinstall files

If I can offer any suggestions in terms of how you organize your postinstall files, I would suggest breaking the files up into directories like this:

Put your non-CentOS application RPMs and tarballs into apps (with a subdirectory for each application), put application configuration files and scripts into appconfig (again with a subdirectory for each application), put OS configuration files (like network config files) into sysconfig, and put general-purpose libraries (those not specifically required by any applications you’re installing) into libs.

Of these strategies, the organization of apps is by far the most important. When you install applications that are not part of the CentOS distro, you’ll likely have to install additional libraries or utilities to satisfy dependencies in those packages. When you need to refresh your kickstart image, it is helpful to have each app and its dependencies contained in a single directory. If you throw them all into a big directory, you’ll never remember, for example, that mhash is in there because aide requires it.

External repositories

I have found the following repositories to be reliable sources of packages that aren’t included in the CentOS distro:

  • EPEL – Extra Packages for Enterprise Linux
  • repoforge – formerly RPMforge; DAG repository now redirects to this
  • ATrpms – good place to get ffmpeg rpms
  • ELrepo – source for hardware drivers

Good luck building your custom installation disc. I welcome any comments or suggestions you might have for this guide!

Part 1  •  Part 2  •  Part 3  •  Part 4

Join the Conversation


  1. Great guide !

    After install I have to update the packages. Maybe it is a better idea to start with actual
    packages in the first place.

  2. Hi, thank you for this guide, it works flawlessly if i mount the iso in Virtual Box, but if i write the iso to an usb pen it doesn’t boot, is there anyway to do this?

    1. Here’s how I’ve burned these ISO images to USB flash drive (using a Mac):

      Type ‘diskutil list’. You’ll see your primary hard drive (probably listed under /dev/disk0) and your flash drive, which will be listed as /dev/disk#, with # being any number that isn’t zero. REMEMBER THE DISK LOCATION

      In the next line, type

      diskutil unmountDisk /dev/disk#

      (where you replace /dev/disk# with the proper device path for your flash drive)

      You’ll see this message on success:

      Unmount of all volumes on disk# was successful

      Now type

      dd if=/path/to/image.iso of=/dev/rdisk# bs=1m'

      NOTE the “r” in front of the disk device name. This makes things about 8 times faster, in my experience.

      To see progress, find the PID of the dd command and send the SIG_INFO signal (signal #29):

      kill -29 16573

      when done, eject the disk:

      diskutil eject /dev/disk#

      1. Hello, thank you for the reply, i found out that in linux we have to do:
        isohybrid image.iso (this is needed to function in BIOS and UEFI)
        sudo dd if=image.iso of=/dev/sdX bs=4k

  3. Hi, Great article and thanks for sharing.

    I found that during USB install of custom ISO, the ‘source’ directory disappears once after packages getting installed.
    My points.
    1. I have put all my files need to copy in source file during creation of ISO.
    2. I want to copy file say txt.1 txt.2 or dir1 from source to respective paths(all done in –nochroot).
    3. After packages installed, the source file is missing/disappears.
    4. But its ok if i use same custom iso to install using CD/DVD. only by USB method its problem to copy these files.
    5. I tried many ways to burn custom iso to USB(livecd-tools, unetbootin, dd etc).

    6. I had found one solution that needs to copy iso to root path of USB so during post section when source files disappears, i need to mount it again on some other path and then i should copy required files needed.

    7. Problem here is i should maintain two iso for CD/DVD and USB. And need to put iso again to home path and distribution is again one more problem.

    8. So my agenda is to have single custom ISO which can be used for both CD/DVD or USB.

    Thanks in advance.

  4. Hi,
    Thanks for writing this article. I have added additional rpms in the Packages directory.
    And then executed following command.
    createrepo -u “media://$discinfo” -g /var/tmp/kickstart_build/7b32e61a7136e672d3d72b472c6ebd99313c9a95b9be2f16fe2faf71825a656c-comps-Workstation.x86_64.xml .
    In the kickstart file i mentioned repo as
    repo –name=”Custom-CentOS6″ –baseurl=file:///mnt/source –cost=1000
    And the %post section i am trying to install those extra rpms using yum install commands. When i check in the logs post installation i see that rpms are not installed.
    There’s an additional “?” after every command. Eg “yum install -y pkg-name”, is being executed as “yum install -y pkg-name?”. And also commands like “mkdir -p /var/tmp/test” in the post section gets created with a “?” in the end. i.e. “/var/tmp/test?”. Could you please advise.

    1. It sounds like maybe you have a line ending problem? Are you editing your postinstall script on Windows, by any chance? That doesn’t sound *exactly* like what I would expect, but it’s hard to imagine anything else that would affect every command at the very end.

      On another note, I do some RPM installs in my postinstall, but I don’t generally roll those RPMs into the main repo. I put them into my postinstall directories, which get copied over to /root/postinstall (as part of my “stage 1” of postinstall). That’s really just a matter of personal preference.

      If you *do* put the RPMs in the you could just list those packages under %packages in your kickstart script, so there’d be no need to install them during postinstall.

      1. Hi,

        You mention that you do some RPM installs in your postinstall. I am trying to do that but cannot seem to find the missing link. I am using livecd-creator. I want to use local repos to do this but cannot figure out how to copy them over. I do not know how to reference the machine I am running livecd-create from. I tried using /mnt/source as you mentioned above. I am using CentOS 7. Do you have any suggestions?

Leave a comment

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