You are on page 1of 7

8/20/2014

Building a custom CentOS 6 kickstart disc, part 1

Building a custom CentOS 6 kickstart disc, part 1


Wednesday, 04 January 2012 00:00

Note: this series of articles applies to CentOS 6; for CentOS 5, see this series.
CentOS (and of course, it's upstream distro, Red Hat Enterprise Linux) has an extremely powerful, but somewhat poorly documented, tool for rapidly deploying machines
and managing their configuration: kickstart. Kickstart lets you build a custom installation that can run hands-free. So not only is the installation quick and easy for you, you
can be confident that your machines are configured exactly the way you want them to be.
Imagine that you have 25 web servers (or a mix of web servers, database servers, mail servers, etc.). It would be highly desirable to install identical software packages on
all of those machines. In that way, you know that any application you build will run the same way on all machines.
If you use the standard install DVD, achieving such uniformity can be challenging. During the installation, it's always possible that you might accidentally select a different
mix of packages for one machine, especially if you are not using one of the standard installation types. Further, it's quite likely that for your production environment you might
need some additional packages that are not part of the standard CentOS distribution. For example, in our environment, we add apps
like aide, analog, httperf, ganglia,iptraf, memcached, nagios, and swatch. If you have to add these packages manually after installation, you'll spend a lot of time,
and you might overlook a machine or a package, leading to inconsistent behavior down the road.
In addition to your software packages, you will likely need to make various system and software configurations. For example, you may need to configure httpd or mysql, or
maybe you need to add a group to /etc/groupor a user to /etc/passwd. It is critical that these configurations be done consistently on all machines.
The solution is to predefine your package selections with kickstart and let the automated installer guarantee the installation of the same applications on all machines.
Further, the postinstaller capabilities of kickstart will allow you to install non-distro applications and perform any system configuration that you can do from a shell script.
If you want to make your life really easy, you can set up your kickstart to run from a single DVD.

Prepare a build system


You will need a CentOS 6 machine on which to assemble the packages and build the custom ISO file. This can be a physical or a virtual machine; my build machine runs
under VMWare Fusion on a Mac. Download the two DVD ISOs for the install media. Be sure to validate your MD5 checksums before you get started. If you are going to
build on a physical machine, burn the ISOs to DVDs. If you're using a virtual build machine, you can just mount the ISOs directly.
Install CentOS 6 on your build machine; choose "Desktop" for the installation type (unless you plan to build custom packages from source; if you need to do that, you'll need
to install the development tools as well).
On the build system, create a build directory: ~/kickstart_build. Create subdirectories like this:
~/kickstart_build
+-- isolinux
|
+-- Packages
|
+-- images
|
+-- ks
+-- utils
Copy all the files from the isolinuxdirectory on CentOS disc 1 into your ~/kickstart_build/isolinuxdirectory. Also copy .discinfofrom CentOS disc 1 into
your~/kickstart_build/isolinuxdirectory
Copy all the files from the imagesdirectory on CentOS disc 1 into your ~/kickstart_build/isolinux/imagesdirectory.
Get the comps.xml file from repodata. In RHEL/CentOS 6, this file is no longer called just "comps.xml"; instead, it has some horrendous hex string for a name. In CentOS
6.2, it is named bedb7dc8fdf920deffbdc5a70ea0d6d77255656556184f5e996e8a88a63d145c-c6-x86_64-comps.xml.gz. Copy
it to~/kickstart_build/comps.xml.gzand gunzip it so that you have ~/kickstart_build/comps.xml.
Your kickstart config file will go into ~/kickstart_build/isolinux/ks. I like to have a separate directory for this, because I build a series of different config files for
different machines or classes of machines.

Start from a sample configuration file


It is always best to start with a sample configuration file. CentOS makes it easy for you to get your hands on one. Just perform a standard installation on a machine. After the
install, look in look in /root/anaconda-ks.cfgto get a sample kickstart configuration file.
Copy this file into ~kickstart_build/isolinux/ks/ks.cfg. Edit the file and find the partitioning information that is commented out; it will have the following note above
it:
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
Uncomment all the lines regarding the disk partitioning. If you don't do this, your kickstart will have no partition on which to install the selected packages.
Note that the drive configuration here reflects the configuration of your build machine. If that is different from your target machine (for example, your build machine might use

http://smorgasbork.com/component/content/article/35-linux/128-building-a-custom-centos-6-kickstart-disc-part-1

1/2

8/20/2014

Building a custom CentOS 6 kickstart disc, part 1

IDE drives, and your target might use SCSI, or you may want to use software RAID on the target machine), you'll have to edit some of these lines. When you're getting
started, it's easiest if you use a build machine configured identically to your target machine.

Copy the RPMs


You don't have to do this, but it makes your life easier to have all the RPMs in a single directory. Note that for our custom disc, we'll copy just the RPMs we need to install, but
since we're going to need to quickly access various RPMs, it's more efficient to put all of them into a temporary directory. Copy all the files from the Packages folder on DVD
1 to ~kickstart_build/all_rpms. Repeat for DVD 2.
If you have CentOS CDs, copy all the RPMs onto your build machine in a temporary directory. You won't need most of them, but when you're tracking down dependencies, it
beats switching discs in and out. If you have a DVD, you don't need to worry about this.

Determine which packages to include


Look in the file ~kickstart_build/comps.xml(which you copied from repodata/comps.xmlon disc 1 of the CentOS distribution). This defines the packages and their
groups.
Your baseline kickstart configuration file will list the packages that are to be installed (under %packages). Groups are noted with a leading @. Leave @coreand @basein the
file, since those have system-critical packages in them.
If you want to really trim down your package list to make a tight distribution, you can remove other groups or replace the groups with the names of just packages that you
want from those groups, using comps.xmlas a reference for which packages are in each group. You can explicitly exclude a package by listing it with a -prepended to the
name.
Next comes the most challenging part -- compiling the RPMs and resolving dependencies.

http://smorgasbork.com/component/content/article/35-linux/128-building-a-custom-centos-6-kickstart-disc-part-1

2/2

8/20/2014

Building a custom CentOS 6 kickstart disc, part 2

Building a custom CentOS 6 kickstart disc, part 2


Wednesday, 04 January 2012 00:00

Note: this series of articles applies to CentOS 6; for CentOS 5, see this series.
Once you've decided which packages you're going to include in your kickstart disc, it's time to pull them all together.
Which RPMs do you need? Assuming that you are including at least the @core and @base package groups (and you should), you'll need the RPMs for all the packages in
those groups.
One way to obtain the list of RPMs you need is to look in the file comps.xmlfor the core and base groups. You will see XML like this:
<group>
<id>core</id>
<name>Core</name>
...
<packagelist>
<packagereq type="default">Deployment_Guide-en-US</packagereq>
<packagereq type="mandatory">SysVinit</packagereq>
<packagereq type="mandatory">authconfig</packagereq>
<packagereq type="mandatory">basesystem</packagereq>
<packagereq type="mandatory">bash</packagereq>
<packagereq type="mandatory">centos-release</packagereq>
<packagereq type="mandatory">coreutils</packagereq>
<packagereq type="mandatory">cpio</packagereq>
...
</packagelist>
</group>

At a bare minimum, you will want all the required packages from within the baseand coregroups. Look for <packagereq type="mandatory">and <packagereq
type="default"> entries within the <group>tags. This tells you which packages to get. These package names correspond to the names of the RPM files.
To make this easier, I have built a script to parse the comps.xmlfile and gather all the non-optional packages for the baseand corepackage groups.
Downloadparse_comps.pland save it in your ~/kickstart_build/utilsdirectory.
Before you can run parse_comps.pl, you'll need to install some perl libraries:
cd ~/kickstart_build/all_rpms
sudo rpm -Uvh \
perl-Compress-Raw-Zlib-2.023-119.el6.x86_64.rpm \
perl-Compress-Zlib-2.020-119.el6.x86_64.rpm \
perl-HTML-Parser-3.64-2.el6.x86_64.rpm \
perl-HTML-Tagset-3.20-4.el6.noarch.rpm \
perl-IO-Compress-Base-2.020-119.el6.x86_64.rpm \
perl-IO-Compress-Zlib-2.020-119.el6.x86_64.rpm \
perl-libwww-perl-5.833-2.el6.noarch.rpm \
perl-URI-1.40-2.el6.noarch.rpm \
perl-XML-Parser-2.36-7.el6.x86_64.rpm \
perl-XML-Simple-2.18-6.el6.noarch.rpm
Run it this way:
cd ~/kickstart_build/isolinux/Packages
~/kickstart_build/utils/parse_comps.pl ~/kickstart_build/comps.xml ~/kickstart_build/all_rpms x86_64

Add your own RPMs


If you want to add any RPMs not included in the baseand coregroups (for example, httpd, php, or mysql), copy those into
the ~/kickstart_build/isolinux/Packagesdirectory at this time.

Gather dependencies
Now we have all the baseand coreRPMs in our ~/kickstart_build/isolinux/Packagesdirectory, along with any other RPMs you've added, but many are missing
their dependencies. So the next step is to track down all the dependencies of these packages and throw those into the directory, too. You can use another
script,follow_deps.pl, to perform this step.

http://smorgasbork.com/component/content/article/35-linux/129-building-a-custom-centos-6-kickstart-disc-part-2

1/2

8/20/2014

Building a custom CentOS 6 kickstart disc, part 2

cd ~/kickstart_build/isolinux/Packages
~/kickstart_build/utils/follow_deps.pl ~/kickstart_build/all_rpms x86_64

Testing dependencies
Once you've got a set of RPMs ready, you'll need to test the dependencies of the RPMs. Each RPM may require that other RPMs be installed in order for it to be installed. If
each RPM's dependencies are included in the set of RPMs, then all the dependencies are resolved. The objective is to have a set of RPMs that have no unresolved
dependencies.
To test the dependencies in your set of RPMs, run these commands:
mkdir /tmp/testdb
rpm --initdb --dbpath /tmp/testdb
rpm --test --dbpath /tmp/testdb -Uvh *.rpm
If you find you have unresolved dependencies (and you will almost certainly have some), you can do one of two things:
remove the RPM with the unresolved dependencies (a good idea if the RPM is going to set off a chain of dependencies that you don't want, for example X Windows on
a server class installation)
track down the RPMs to fulfill the dependency
Here, again, you need a little bit of savvy to determine which packages should be removed. In general, if the package is one that you explicitly added to the base and core
groups, then you'll probably want to find the dependencies and include them. If it's an RPM that you don't really want (one that got matched by the wildcard, for example), you
might decide to eliminate that RPM.

Resolving dependencies
The follow_deps.plscript should get all your dependencies automatically. But if it doesn't (and it might not, especially if you've added some additional RPMs to the mix),
you'll have to track down the dependencies manually.
Finding the RPMs to satisfy dependencies can be easier said than done. Sometimes the capability dependencies listed don't match the name of the RPM. For example, you
might get something like:
/usr/bin/strip is needed by redhat-lsb-3.1-12.3.EL.el5.centos.x86_64
It turns out that /usr/bin/stripis provided by binutils.
If you're not sure what RPM provides one of these dependencies, you can use RPM itself to query for the right package (assuming the right package is installed on the
queried system -- this is where it is very helpful to have a machine that has all the RPMs installed).
rpm -q --whatprovides /usr/bin/strip
This is an iterative process. Be prepared to spend a while chasing down these dependencies to build a fine-tuned collection of RPMs with no unresolved dependencies.
The next step is to build your disk image. I will cover that in the next installment.

http://smorgasbork.com/component/content/article/35-linux/129-building-a-custom-centos-6-kickstart-disc-part-2

2/2

8/20/2014

Building a custom CentOS 6 kickstart disc, part 3

Building a custom CentOS 6 kickstart disc, part 3


Wednesday, 04 January 2012 00:00

Note: this series of articles applies to CentOS 6; for CentOS 5, see this series.
Now that you've compiled your RPMs, you need to build a disk image from which to perform the kickstart.

Create the repository


Install createrepo so that you can create a repository. If you've copied all the RPMs to ~kickstart_build/all_rpmsas suggested earlier, just do this:
cd ~kickstart_build/all_rpms
rpm -Uvh createrepo*rpm deltarpm*rpm python-deltarpm*rpm
You need to build the repodata for your install disc. These files provide the installer information about the available packages. On your build machine, you should have
already copied the repodata/comps.xmlfile from the CentOS disc 1 to ~/kickstart_build. Use createrepoto build the repository info.
cd ~/kickstart_build/isolinux
declare -x discinfo=`head -1 .discinfo`
createrepo -u "media://$discinfo" -g ~/kickstart_build/comps.xml .
This will create a repodatadirectory under ~/kickstart_build/isolinuxwith the repository data files in it.

Build the ISO


We're finally ready to build the ISO image that we can burn to CD.
cd ~/kickstart_build
mkisofs -o custom.iso -b isolinux.bin -c boot.cat -no-emul-boot \
-boot-load-size 4 -boot-info-table -R -J -v -T isolinux/
/usr/lib/anaconda-runtime/implantisomd5 custom.iso
You should now have an ISO image in custom.iso.

Testing the ISO


Rather than spending the time to burn the CD and perform a physical installation, you can test the ISO using a virtual machine, which you can run under a program like
VirtualBox.
When the system (virtual or physical) boots up, you'll see your standard CentOS installation prompt. Before the countdown expires, hit ESC and type
linux ks=cdrom:/ks/ks.cfg
If you chose to use some other name for your kickstart config file, replace ks.cfgwith the name of your configuration file. You may choose to name your configuration files
based on hostname or server class. If you have to use a test configuration file to get around the SATA limitations of qemu, you may call that file test.cfgor something
similar.
Your installation should proceed automatically.
Now you have a working custom kickstart disc. To really take advantage of the power of kickstart, you'll most likely need a custom postinstallation script to configure the
system according to your specs. We'll cover that in the next installment in this series.

http://smorgasbork.com/component/content/article/35-linux/130-building-a-custom-centos-6-kickstart-disc-part-3

1/1

8/20/2014

Building a custom CentOS 6 kickstart disc, part 4

Building a custom CentOS 6 kickstart disc, part 4


Wednesday, 04 January 2012 00:00

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 %postdirective.
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 %postsection are run in a chroot environment, where /mnt/sysimageappears as the /directory. This lets you use "normal" paths to
configuration files like /etcinstead 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.
%post --nochroot
#!/bin/sh
set -x -v
exec 1>/mnt/sysimage/root/kickstart-stage1.log 2>&1
echo "==> copying files..."
cp -r /mnt/source/postinstall /mnt/sysimage/root/postinstall
In our case, we've put all our postinstallation files into the postinstalldirectory under the ~/kickstart_build/isolinuxdirectory. Note that the isolinuxdirectory 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/postinstallon the new system's hard drive.
We're now ready to run stage 2 of the postinstall, where we actually use the postinstallation files.
%post
#!/bin/sh
set -x -v
exec 1>/root/kickstart-stage2.log 2>&1
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 postinstallfiles, I would suggest breaking the files up into directories like this:
~/kickstart_build/isolinux/postinstall
+-- apps

http://smorgasbork.com/component/content/article/35-linux/131-building-a-custom-centos-6-kickstart-disc-part-4

1/2

8/20/2014

Building a custom CentOS 6 kickstart disc, part 4


+-- appconfig
+-- sysconfig
+-- libs

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 appsis 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!

http://smorgasbork.com/component/content/article/35-linux/131-building-a-custom-centos-6-kickstart-disc-part-4

2/2