Kickstart
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 . . Lots of packages truncated! . 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
In this example, the install media is on our local NFS server. However, you could just as easily point it to you favourite HTTP mirror:
url --url http://mirror.internode.on.net/pub/centos/5.5/os/x86_64
3. Make the kickstart file world readable
chmod 644 kickstart.ks
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.