Difference between revisions of "Kickstart"

From Peter Pap's Technowiki
Jump to: navigation, search
(Make a Kickstart configuration file)
Line 31: Line 31:
 
== Make a Kickstart configuration file ==
 
== Make a Kickstart configuration file ==
  
 +
1. Make a directory to hold the Kickstart configuration file on the NFS server
  
 +
  mkdir /export/centos/kickstart
 +
 +
2. Create a file in this directory called kickstart.ks.  An example kickstart file is shown below:
 +
 +
  #
 +
  # Kickstart config file.  Produces the actual kickstart file to be given
 +
  # to anaconda.  Documentation for each option is listed in the comments
 +
  # above where the option is produced. 
 +
  #
 +
  # This file documents as many of the kickstart keywords and options as
 +
  # possible.  The models do not support all the options, but more are
 +
  # added as needed.
 +
  #
 +
  # Some document names are abbreviated:
 +
  #
 +
  # SAG: RHEL4 System Administration Guide, English edition
 +
  # (rhel-sag-en.pdf)
 +
  #
 +
  #platform=x86, AMD64, or Intel EM64T
 +
  # Required
 +
  #
 +
 
 +
 
 +
  # Kickstart Specific Settings
 +
  #
 +
  # lang
 +
  # SAG p9
 +
  # lang is the language used during install.
 +
  # langsupport is the set of languages to be supported on the installed system.
 +
  # keyboard is the keyboard connected to the system.
 +
  lang en_US
 +
 
 +
  # Perform kickstart in text mode.  There's no need for a graphical build,
 +
  # even off a CD/DVD.
 +
  # text: SAG pg16
 +
  text
 +
 
 +
 
 +
  # Install or upgrade?
 +
  # install: SAG p8
 +
  # upgrade: SAG p16
 +
  install
 +
 
 +
  # Use NFS installation media
 +
  nfs --server=buildserver.mydomain.com --dir=/export/centos/5.5/os/x86_64
 +
 
 +
  # Network settings
 +
  network --device eth0 --bootproto static --ip 192.168.1.3 --netmask 255.255.255.0 --gateway 192.168.1.254 --nameserver 192.168.11.253
 +
 
 +
  # What to do after installation
 +
  # poweroff: SAG pg 13
 +
  # halt: SAG pg 8
 +
  # reboot: SAG pg 14
 +
  poweroff
 +
 
 +
  #
 +
  # System Specific Settings
 +
  #
 +
 
 +
  # langsupport and keyboard
 +
  langsupport --default=en_US en_GB
 +
  keyboard us
 +
 
 +
  # System Devices
 +
 
 +
  # Bootloader
 +
  # SAG pg 5
 +
  bootloader --append="" --location=mbr
 +
 
 +
  # Network information
 +
  # SAG pp10-12
 +
  #
 +
 
 +
  # SELinux configuration
 +
  # Need to add SELinux Policy support through policy modules.
 +
  #
 +
  selinux --disabled
 +
 
 +
  # System authorization information
 +
  # SAG pp 2-5
 +
  auth --enablemd5 --enableshadow
 +
 
 +
 
 +
  # Autoconfigure mouse
 +
  # SAG p10
 +
  # "mouse" with no options autodetects the mouse
 +
  # Optionally, it can have three arguments.
 +
  #      [--device=ttyS0] [--emulthree] [mousetype]
 +
  #
 +
  mouse
 +
 
 +
  # Firewall configuration
 +
  # SAG p 7
 +
  firewall --disabled
 +
 
 +
  # Run the Setup Agent on first boot
 +
  # Mode is one of enabled, disabled, reconfig
 +
  # SAG pp 7-8
 +
  firstboot --disable
 +
 
 +
  #
 +
  # Root password
 +
  #
 +
  # SAG pg 15
 +
  rootpw --iscrypted XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 +
 
 +
  # System timezone (set via %pre?)
 +
  # timezone: SAG pg16
 +
  timezone --utc Australia/Melbourne
 +
 
 +
  # X or no X
 +
  # Either "skipx" or "xconfig --startxonboot"
 +
  # skipx: SAG p15
 +
 
 +
  skipx
 +
 
 +
 
 +
  #clearpart --initlabel
 +
  # Disk partitioning information
 +
 
 +
  #
 +
  # Partition information
 +
  # zerombr: SAG p17
 +
  zerombr yes
 +
 
 +
  # NOTE - Partition information is generated in the pre scripts
 +
  %include "/tmp/partitions.ks"
 +
 
 +
  #
 +
  # OS Specific Tags
 +
  # Use this section for tags specific to a particular config
 +
  #
 +
  #entitlement
 +
  key bbe5b781bb89f5b6
 +
 
 +
  # Packages
 +
  # SAG pp 18-19
 +
  # --nobase is documented in various mailing lists.  For example,
 +
  # http://www.sage.org/lists/sage-members-archive/2006/msg01378.html.
 +
  #
 +
  %packages --nobase --resolvedeps
 +
  aide
 +
  at
 +
  bc
 +
  bind-utils
 +
  binutils
 +
  compat-libstdc++-296
 +
  cpio
 +
  cpufreq-utils
 +
  cpuspeed
 +
  crontabs
 +
  curl
 +
  dhclient
 +
  eject
 +
  expect
 +
  finger
 +
  ftp
 +
  gnupg
 +
  httpd
 +
  ksh
 +
  libevent
 +
  libgssapi
 +
  libidn
 +
  lsof
 +
  ltrace
 +
  man
 +
  man-pages
 +
  mod_ssl
 +
  nc
 +
  netpbm
 +
  netpbm-progs
 +
  nfs-utils
 +
  nmap
 +
  nscd
 +
  nss_ldap
 +
  ntp
 +
  openssh
 +
  openssh-clients
 +
  openssh-server
 +
  oprofile
 +
  parted
 +
  patch
 +
  perl
 +
  pstack
 +
  rcs
 +
  rsync
 +
  sendmail
 +
  sharutils
 +
  sqlite
 +
  strace
 +
  subversion
 +
  sudo
 +
  sysstat
 +
  tcp_wrappers
 +
  tcpdump
 +
  tcsh
 +
  time
 +
  tmpwatch
 +
  traceroute
 +
  unzip
 +
  usbutils
 +
  vim-common
 +
  vim-enhanced
 +
  vixie-cron
 +
  wget
 +
  which
 +
  xinetd
 +
  yum
 +
  yum-utils
 +
  zip
 +
 
 +
  #
 +
  # Pre-install scripts
 +
  # SAG pp 19-21
 +
 
 +
  # Partition information generator
 +
  %pre --interpreter=/usr/bin/python
 +
  import re
 +
  import os
 +
 
 +
  partitions = [['/', 4096, 0, 0],['/boot', 100, 0, 1],['swap', 8192, 0, 0],['/var', 1, 1, 0],['/usr', 8192, 0, 0],['/home', 8192, 0, 0]]
 +
  m_ide = re.compile(r'(hd[a-z]):\s+([0-9]+)\s+sectors\s+\(([0-9]+)\sMB\)')
 +
  m_scsi = re.compile(r'SCSI\s+device\s+(sd[a-z]):\s+([0-9]+)\s+.*\(([0-9]+)\s+MB\)')
 +
 
 +
  i = dict()
 +
  s = dict()
 +
  pipe = os.popen('dmesg', 'r')
 +
  for line in pipe.readlines():
 +
    m = m_ide.search(line)
 +
    if m:
 +
      i[m.group(1)] = [m.group(2), m.group(3)]
 +
    m = m_scsi.search(line)
 +
    if m:
 +
      s[m.group(1)] = [m.group(2), m.group(3)]
 +
 
 +
  ide_drives = list()
 +
  scsi_drives = list()
 +
  do_drives = list()
 +
  for k in i.keys(): ide_drives.append([k, i[k][0], i[k][1]])
 +
  for k in s.keys(): scsi_drives.append([k, s[k][0], s[k][1]])
 +
 
 +
  if (len(ide_drives) > 0):
 +
    if ((len(ide_drives) == 2) and ((ide_drives[0][1] == ide_drives[1][1]) and (ide_drives[0][2] == ide_drives[1][2]))): do_drives = ide_drives
 +
    else: do_drives = [['hda']]
 +
  elif (len(scsi_drives) > 0):
 +
    if ((len(scsi_drives) == 2) and ((scsi_drives[0][1] == scsi_drives[1][1]) and (scsi_drives[0][2] == scsi_drives[1][2]))): do_drives = scsi_drives
 +
    else: do_drives = [['sda']]
 +
  else: do_drives = [['sda']]
 +
 
 +
  pfile = open("/tmp/partitions.ks", "w")
 +
  pfile.write("clearpart --all --initlabel --drives=%s\n" % ",".join([x[0] for x in do_drives]))
 +
  rstr = ''
 +
 
 +
  for index, p in enumerate(partitions):
 +
    if (len(do_drives) == 2):
 +
      pfile.write("partition raid.0%d --size=%d %s %s --ondisk=%s\n" % (index, p[1], ((p[2] == 1) and '--grow' or ''), ((p[3] == 1) and '--asprimary' or ''), do_drives[0][0]))
 +
      pfile.write("partition raid.1%d --size=%d %s %s --ondisk=%s\n" % (index, p[1], ((p[2] == 1) and '--grow' or ''), ((p[3] == 1) and '--asprimary' or ''), do_drives[1][0]))
 +
      rstr += "raid %s --fstype=%s --device=md%d --level 1 raid.0%d raid.1%d\n" % (p[0], ((p[0] == 'swap') and 'swap' or 'ext3'), index, index, index)
 +
    else:
 +
      pfile.write("partition %s --fstype=%s --size=%d %s %s --ondisk=%s\n" % (p[0], ((p[0] == 'swap') and 'swap' or 'ext3'), p[1], ((p[2] == 1) and '--grow' or ''), ((p[3] == 1) and '--asprimary' or ''), do_drives[0][0]))
 +
 
 +
  pfile.write(rstr)
 +
  pfile.close()
 +
 
 +
  pfile = open("/tmp/partition-script.ks", "w")
 +
  if (len(do_drives) == 2):
 +
    pfile.write("\n%post\n/sbin/grub << EOF\n")
 +
    for d in do_drives:
 +
      pfile.write("device (hd0) /dev/%s\nroot (hd0,0)\nsetup (hd0)\n" % d[0])
 +
    pfile.write("quit\n")
 +
    pfile.write("EOF\n")
 +
  pfile.close()
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
  #
 +
  # OS Specific Pre Scripts
 +
  #
 +
 
 +
 
 +
  # NOTE - Grub setup, if needed
 +
  %include "/tmp/partition-script.ks"
 +
 
 +
  #
 +
  # Set up the serial console
 +
  #
 +
  %post
 +
  echo ":: Setting up Serial Console ::"  >> /root/post.log
 +
  perl -p -i -e 's/^(default.*)$/$1\nserial --unit=0 --speed=9600 --data=8 --parity=no --stop=1\nterminal --timeout=5 serial console/' /boot/grub/grub.conf >> /root/post.log 2>&1
 +
  perl -p -i -e 's/^(\s+kernel.*)$/$1 console=tty0 console=ttyS0,9600/' /boot/grub/grub.conf >> /root/post.log 2>&1
 +
  echo "" >> /etc/inittab
 +
  echo "# Run serial console on ttyS0" >> /etc/inittab
 +
  echo "S1:2345:respawn:/sbin/agetty ttyS0 9600 vt100" >> /etc/inittab
 +
  echo "ttyS0" >> /etc/securetty
 +
  echo ":: Done Setting up Serial Console ::"  >> /root/post.log
 +
 
 +
 
 +
  #
 +
  # Save the configuration information for later reference
 +
  #
 +
  %post
 +
  echo ":: Saving configuration information ::"  >> /root/post.log
 +
  mkdir -p /var/installation
 +
  cd /var/installation
 +
  mv /root/install.log* /var/installation >> /root/post.log 2>&1
 +
  mv /root/anaconda-ks.cfg /var/installation >> /root/post.log 2>&1
 +
  cp /tmp/partition.ks /var/installation >> /root/post.log 2>&1
 +
  mv /root/post.log /var/installation
 +
 
 +
 
 +
  #
 +
  # Post-install scripts
 +
  # SAG pp 21-22
 +
  %post --interpreter /bin/bash
 +
  /sbin/chkconfig xfs off
 +
  /sbin/chkconfig lvm2-monitor off
 +
  /sbin/chkconfig sendmail off
 +
  /sbin/chkconfig autofs off
 +
  /sbin/chkconfig portmap off
 +
  /sbin/chkconfig ntpd on
 +
 
 +
  %post --interpreter /bin/bash
 +
  # We have to set up the issue files here because it changes for every
 +
  # revision of the OS.
 +
  rm -f /etc/issue /etc/issue.net
 +
 
 +
  cat <<EOT > /etc/issue
 +
  ***********************************************************************
 +
  * Access to this computer system is limited to authorised users only. *
 +
  * Unauthorised users may be subject to prosecution under the Crimes  *
 +
  *                      Act or State legislation                      *
 +
  *                                                                    *
 +
  *  Please note, ALL CUSTOMER DETAILS are confidential and must      *
 +
  *                          not be disclosed.                          *
 +
  ***********************************************************************
 +
  EOT
 +
 
 +
  cp /etc/issue /etc/issue.net
 +
 
 +
  # Add users
 +
  echo ":: Adding users and groups ::" >> /var/installation/post.log
 +
  groupadd -g 100 myusers >> /var/installation/post.log 2>&1
 +
  useradd -c "Peter Papagiannopoulos" -d /home/ppapa -m -s /bin/tcsh -u 1000 -g 100 -p 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX' ppapa >> /var/installation/post.log 2>&1
 +
 
 +
  echo ":: Adding users to wheel group ::" >> /var/installation/post.log
 +
  cp -p /etc/group /etc/group.bk>> /var/installation/post.log 2>&1
 +
  sed -e 's/wheel:x:10:root/wheel:x:10:root,ppapa/' /etc/group.bk > /etc/group
  
 
== Building the boot CD ==
 
== Building the boot CD ==

Revision as of 06:08, 8 November 2010

Kickstart is awesome for automating the building CentOS/RedHat servers. There are a number of ways that you can do it, such as PXE booting of the network etc, but the way I choose to do it requires a simple boot CD.

In this example, our build media will be stored on a local NFS share.

Creating the media repository

1. Download the latest DVD ISO from your favourite mirror.

2. Either burn the ISO to a DVD or soft mount it on a Linux/Unix server.

3. Make a directory that you want to use as your NFS share

 mkdir /export/centos
 chmod 755 /export/centos

4. Share this directory over NFS.

Clear here for instructions on how to Create an NFS share with Solaris.

5. Create a directory to hold the contents of the DVD

 mkdir -p /export/centos/5.5/os/x86_64
 chmod 755 /export/centos

6. Copy the contents of the DVD in to this directory

 cd /export/centos/5.5/os/x86_64
 cp -pr PATH_TO_DVD/* .


Make a Kickstart configuration file

1. Make a directory to hold the Kickstart configuration file on the NFS server

 mkdir /export/centos/kickstart

2. Create a file in this directory called kickstart.ks. An example kickstart file is shown below:

 #
 # Kickstart config file.  Produces the actual kickstart file to be given
 # to anaconda.  Documentation for each option is listed in the comments 
 # above where the option is produced.  
 #
 # This file documents as many of the kickstart keywords and options as
 # possible.  The models do not support all the options, but more are
 # added as needed.
 #
 # Some document names are abbreviated:
 #
 # SAG: RHEL4 System Administration Guide, English edition 
 # (rhel-sag-en.pdf)
 #
 #platform=x86, AMD64, or Intel EM64T
 # Required
 #
 
 
 # Kickstart Specific Settings
 #
 # lang
 # SAG p9
 # lang is the language used during install.
 # langsupport is the set of languages to be supported on the installed system.
 # keyboard is the keyboard connected to the system.
 lang en_US 
 
 # Perform kickstart in text mode.  There's no need for a graphical build,
 # even off a CD/DVD.
 # text: SAG pg16
 text
 
 
 # Install or upgrade?
 # install: SAG p8
 # upgrade: SAG p16
 install
 
 # Use NFS installation media
 nfs --server=buildserver.mydomain.com --dir=/export/centos/5.5/os/x86_64
 
 # Network settings
 network --device eth0 --bootproto static --ip 192.168.1.3 --netmask 255.255.255.0 --gateway 192.168.1.254 --nameserver 192.168.11.253
 
 # What to do after installation
 # poweroff: SAG pg 13
 # halt: SAG pg 8
 # reboot: SAG pg 14
 poweroff
 
 #
 # System Specific Settings
 # 
 
 # langsupport and keyboard
 langsupport --default=en_US en_GB 
 keyboard us
 
 # System Devices
 
 # Bootloader
 # SAG pg 5
 bootloader --append="" --location=mbr
 
 # Network information
 # SAG pp10-12
 #
 
 # SELinux configuration
 # Need to add SELinux Policy support through policy modules.
 #
 selinux --disabled
 
 # System authorization information
 # SAG pp 2-5
 auth --enablemd5 --enableshadow
 
 
 # Autoconfigure mouse
 # SAG p10
 # "mouse" with no options autodetects the mouse
 # Optionally, it can have three arguments.
 #       [--device=ttyS0] [--emulthree] [mousetype]
 #
 mouse
 
 # Firewall configuration
 # SAG p 7
 firewall --disabled
 
 # Run the Setup Agent on first boot
 # Mode is one of enabled, disabled, reconfig
 # SAG pp 7-8
 firstboot --disable
 
 #
 # Root password 
 #
 # SAG pg 15
 rootpw --iscrypted XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
 # System timezone (set via %pre?)
 # timezone: SAG pg16
 timezone --utc Australia/Melbourne
 
 # X or no X
 # Either "skipx" or "xconfig --startxonboot"
 # skipx: SAG p15
 
 skipx
 
 
 #clearpart --initlabel
 # Disk partitioning information
 
 #
 # Partition information
 # zerombr: SAG p17
 zerombr yes
 
 # NOTE - Partition information is generated in the pre scripts
 %include "/tmp/partitions.ks"
 
 #
 # OS Specific Tags
 # Use this section for tags specific to a particular config
 #
 #entitlement
 key bbe5b781bb89f5b6
 
 # Packages
 # SAG pp 18-19
 # --nobase is documented in various mailing lists.  For example,
 # http://www.sage.org/lists/sage-members-archive/2006/msg01378.html.
 #
 %packages --nobase --resolvedeps
 aide
 at
 bc
 bind-utils
 binutils
 compat-libstdc++-296
 cpio
 cpufreq-utils
 cpuspeed
 crontabs
 curl
 dhclient
 eject
 expect
 finger
 ftp
 gnupg
 httpd
 ksh
 libevent
 libgssapi
 libidn
 lsof
 ltrace
 man
 man-pages
 mod_ssl
 nc
 netpbm
 netpbm-progs
 nfs-utils
 nmap
 nscd
 nss_ldap
 ntp
 openssh
 openssh-clients
 openssh-server
 oprofile
 parted
 patch
 perl
 pstack
 rcs
 rsync
 sendmail
 sharutils
 sqlite
 strace
 subversion
 sudo
 sysstat
 tcp_wrappers
 tcpdump
 tcsh
 time
 tmpwatch
 traceroute
 unzip
 usbutils
 vim-common
 vim-enhanced
 vixie-cron
 wget
 which
 xinetd
 yum
 yum-utils
 zip
 
 #
 # Pre-install scripts
 # SAG pp 19-21
 
 # Partition information generator
 %pre --interpreter=/usr/bin/python
 import re
 import os
 
 partitions = [['/', 4096, 0, 0],['/boot', 100, 0, 1],['swap', 8192, 0, 0],['/var', 1, 1, 0],['/usr', 8192, 0, 0],['/home', 8192, 0, 0]]
 m_ide = re.compile(r'(hd[a-z]):\s+([0-9]+)\s+sectors\s+\(([0-9]+)\sMB\)')
 m_scsi = re.compile(r'SCSI\s+device\s+(sd[a-z]):\s+([0-9]+)\s+.*\(([0-9]+)\s+MB\)')
 
 i = dict()
 s = dict()
 pipe = os.popen('dmesg', 'r')
 for line in pipe.readlines():
   m = m_ide.search(line)
   if m:
     i[m.group(1)] = [m.group(2), m.group(3)]
   m = m_scsi.search(line)
   if m:
     s[m.group(1)] = [m.group(2), m.group(3)]
 
 ide_drives = list()
 scsi_drives = list()
 do_drives = list()
 for k in i.keys(): ide_drives.append([k, i[k][0], i[k][1]])
 for k in s.keys(): scsi_drives.append([k, s[k][0], s[k][1]])
 
 if (len(ide_drives) > 0):
   if ((len(ide_drives) == 2) and ((ide_drives[0][1] == ide_drives[1][1]) and (ide_drives[0][2] == ide_drives[1][2]))): do_drives = ide_drives
   else: do_drives = 'hda'
 elif (len(scsi_drives) > 0):
   if ((len(scsi_drives) == 2) and ((scsi_drives[0][1] == scsi_drives[1][1]) and (scsi_drives[0][2] == scsi_drives[1][2]))): do_drives = scsi_drives
   else: do_drives = 'sda'
 else: do_drives = 'sda'
 
 pfile = open("/tmp/partitions.ks", "w")
 pfile.write("clearpart --all --initlabel --drives=%s\n" % ",".join([x[0] for x in do_drives]))
 rstr = 
 
 for index, p in enumerate(partitions):
   if (len(do_drives) == 2):
     pfile.write("partition raid.0%d --size=%d %s %s --ondisk=%s\n" % (index, p[1], ((p[2] == 1) and '--grow' or ), ((p[3] == 1) and '--asprimary' or ), do_drives[0][0]))
     pfile.write("partition raid.1%d --size=%d %s %s --ondisk=%s\n" % (index, p[1], ((p[2] == 1) and '--grow' or ), ((p[3] == 1) and '--asprimary' or ), do_drives[1][0]))
     rstr += "raid %s --fstype=%s --device=md%d --level 1 raid.0%d raid.1%d\n" % (p[0], ((p[0] == 'swap') and 'swap' or 'ext3'), index, index, index)
   else:
     pfile.write("partition %s --fstype=%s --size=%d %s %s --ondisk=%s\n" % (p[0], ((p[0] == 'swap') and 'swap' or 'ext3'), p[1], ((p[2] == 1) and '--grow' or ), ((p[3] == 1) and '--asprimary' or ), do_drives[0][0]))
 
 pfile.write(rstr)
 pfile.close()
 
 pfile = open("/tmp/partition-script.ks", "w")
 if (len(do_drives) == 2):
   pfile.write("\n%post\n/sbin/grub << EOF\n")
   for d in do_drives:
     pfile.write("device (hd0) /dev/%s\nroot (hd0,0)\nsetup (hd0)\n" % d[0])
   pfile.write("quit\n")
   pfile.write("EOF\n")
 pfile.close()
 
 
 
 
 
 
 #
 # OS Specific Pre Scripts
 #
 
 
 # NOTE - Grub setup, if needed
 %include "/tmp/partition-script.ks"
 
 #
 # Set up the serial console
 #
 %post
 echo ":: Setting up Serial Console ::"  >> /root/post.log
 perl -p -i -e 's/^(default.*)$/$1\nserial --unit=0 --speed=9600 --data=8 --parity=no --stop=1\nterminal --timeout=5 serial console/' /boot/grub/grub.conf >> /root/post.log 2>&1
 perl -p -i -e 's/^(\s+kernel.*)$/$1 console=tty0 console=ttyS0,9600/' /boot/grub/grub.conf >> /root/post.log 2>&1
 echo "" >> /etc/inittab
 echo "# Run serial console on ttyS0" >> /etc/inittab
 echo "S1:2345:respawn:/sbin/agetty ttyS0 9600 vt100" >> /etc/inittab
 echo "ttyS0" >> /etc/securetty
 echo ":: Done Setting up Serial Console ::"  >> /root/post.log
 
 
 #
 # Save the configuration information for later reference
 #
 %post
 echo ":: Saving configuration information ::"  >> /root/post.log
 mkdir -p /var/installation
 cd /var/installation
 mv /root/install.log* /var/installation >> /root/post.log 2>&1
 mv /root/anaconda-ks.cfg /var/installation >> /root/post.log 2>&1
 cp /tmp/partition.ks /var/installation >> /root/post.log 2>&1
 mv /root/post.log /var/installation
 
 
 #
 # Post-install scripts
 # SAG pp 21-22
 %post --interpreter /bin/bash
 /sbin/chkconfig xfs off
 /sbin/chkconfig lvm2-monitor off
 /sbin/chkconfig sendmail off
 /sbin/chkconfig autofs off
 /sbin/chkconfig portmap off
 /sbin/chkconfig ntpd on
 
 %post --interpreter /bin/bash
 # We have to set up the issue files here because it changes for every
 # revision of the OS.
 rm -f /etc/issue /etc/issue.net
 
 cat <<EOT > /etc/issue
 ***********************************************************************
 * Access to this computer system is limited to authorised users only. *
 * Unauthorised users may be subject to prosecution under the Crimes   *
 *                       Act or State legislation                      *
 *                                                                     *
 *   Please note, ALL CUSTOMER DETAILS are confidential and must       *
 *                          not be disclosed.                          *
 ***********************************************************************
 EOT
 
 cp /etc/issue /etc/issue.net
 
 # Add users
 echo ":: Adding users and groups ::" >> /var/installation/post.log
 groupadd -g 100 myusers >> /var/installation/post.log 2>&1
 useradd -c "Peter Papagiannopoulos" -d /home/ppapa -m -s /bin/tcsh -u 1000 -g 100 -p 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX' ppapa >> /var/installation/post.log 2>&1
 
 echo ":: Adding users to wheel group ::" >> /var/installation/post.log
 cp -p /etc/group /etc/group.bk>> /var/installation/post.log 2>&1
 sed -e 's/wheel:x:10:root/wheel:x:10:root,ppapa/' /etc/group.bk > /etc/group

Building the boot CD

1. Download the latest DVD ISO of the distro you wish to use. In this case it's CentOS 5.5 x86_64.

2. Either burn the DVD ISO to DVD media or soft mount it on your machine.

3. Make a directory to hold the boot image data

 mkdir bootimage

4. Copy the 'images' and 'isolinux' directories from the DVD into the bootimage folder

 cd bootimage
 cp -pr PATH_TO_DVD/images/ .
 cp -pr PATH_TO_DVD/isolinux/ .

5. Go into the 'isolinux' directory and edit the isolinux.cfg file with the following contents:

 default vrsn-ks
 prompt 5
 timeout 15
 label vrsn-ks
   kernel vmlinuz
   append ip=dhcp ks=nfs:192.168.1.1:/export/install/centos/ks/kickstart.ks initrd=initrd.img kssendmac ksdevice=eth0 lang=en_US
 label linux
   kernel vmlinuz
   append initrd=initrd.img
 label text
   kernel vmlinuz
   append initrd=initrd.img text
 label ks
   kernel vmlinuz
   append ks initrd=initrd.img
 label local
   localboot 1
 label memtest86
   kernel memtest
   append -

In this example, the server will use network interface eth0, will get it's IP from DHCP and will get it's kickstart config file, kickstart.ks, from the nfs server 192.168.1.1 in the specified directory.

If DHCP isn't available, you can specify a static IP like this:

 ip=192.168.1.2 netmask=255.255.255.0 gateway=192.168.1.254 nameserver=192.168.1.253

6. Make a bootable ISO image of this directory:

 cd bootimage
 mkisofs -o ../ks.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -R -J -v -T .

7. Burn the new ISO, ks.iso, to CD using your favourite burning software.