HOWTO: Configure a CentOS 6.0 Network Install Server

Introduction

Installing multiple servers is made much easier with a Network Install Server. With this, each server boots from the Network, and the information about how to install the server is received from the Network Install Server. The Network Install Server comprises four elements:

By the end of this HOWTO you will be able to install a blank server without keyboard interaction beyond a boot-up command and the new server will be fully functional at the end of it.

This configuration is ideal if you need to re-install your server frequently or are using a virtualization system such as VMware ESXi to configure many servers.

Before You Begin

Recommended Server Configuration

Before you can install other servers, you must install CentOS on a system. If you are using VMware ESXi for this purpose, then the following statistics can be used:

This server should probably be a standalone server without any other accounts other than root on it. However, you may want to link it to a centralized authentication scheme or add a system administrator account to it. I use CentOS 6.0 for my install - some elements may need to be configured differently on earlier versions of CentOS.

In Place Editing

Where possible, I use in-place editing to provide a cut-and-paste ability. If you see perl -npe or cat <<EOF, then this is used in place of vi or similar editor. If you feel more comfortable with an editor, feel free to use it.

Entering Commands

All commands should be executed with "root" privileges on the Network Install Server. Refer to Becoming Root for more information.

Register the Network Install Server in DNS

The Network Install Server must be in your local DNS or the /etc/hosts file of every single client system.

Required Packages

The following will install all the required packages:

yum -y install rsync httpd vixie-cron dhcp tftp-server syslinux make perl

Obtain a copy of the CentOS 6.0 Distribution

Pick a mirror from the CentOS Public Mirrors List that supports rsync and note the host and remote directory. You will need this information when creating your repository mirror script.

cd /etc/cron.weekly
cat <<EOF >update-centos
#!/bin/sh
# Replace this information with your mirror information
MIRROR=rsync://REPLACE.WITH.YOUR.MIRRORHOST/PATH/centos/6.0
LOCALDIR=/var/www/html/centos/6.0

for i in os updates; do
    rsync -aH $MIRROR/$i $LOCALDIR
done
EOF
chmod 0755 update-centos
mkdir -p /var/www/html/centos/6.0
./update-centos &

Replace REPLACE.WITH.YOUR.MIRRORHOST/PATH with the name of the rsync host and path you are using for your mirror.

At this point, the CentOS distribution (both OS and UPDATES) will be downloaded from a central repository mirror. This will take several hours, and will run in the background. You will want to run this command on a regular basis - by placing in /etc/cron.weekly, this will happen once a week. I found that CentOS 6.0 does not automatically start crond or install an /etc/crontab that does this. The following will configure crond appropriately if this is the case for you.

cat <<EOF >>/etc/crontab
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
EOF
service crond start
chkconfig crond on

Create a CentOS 6.0 Distribution Server

A distribution server is a web server that provides the OS distribution files. The following configured the web server appropriately for this function.

cd /var/www/html/centos
ln -s 6.0 6
iptables -I INPUT -m state --state new -m tcp -p tcp --dport 80 -j ACCEPT
service iptables save
service httpd start
chkconfig httpd on

Since you now have a localized copy of the os and updates sections of the repository, you will want to alter the repository definitions on all systems to use the new repository. The following will make this happen on client systems:

cd /etc/yum.repos.d
perl -npe '/mirrorlist=.*repo=os/ && s/^/#/' -i CentOS-Base.repo
perl -npe '/mirrorlist=.*repo=updates/ && s/^/#/' -i CentOS-Base.repo
perl -npe '/#baseurl=.*\/os\// && s/^#//' -i CentOS-Base.repo
perl -npe '/#baseurl=.*\/updates\// && s/^#//' -i CentOS-Base.repo
perl -npe '/^baseurl=/ && s/mirror.centos.org/NETINSTALL-HOST/' -i CentOS-Base.repo

Replace NETINSTALL-HOST with the name of your host within DNS or the /etc/hosts file.

Configuring the DHCP Server

The DHCP Server needs to be configured for your network. My network is 192.168.1.0, and my DNS servers are 192.168.1.2 and 192.168.1.3. Your network is probably different, so alter the IP addresses accordingly.

cat <<EOF >/etc/dhcp/dhcpd.conf
option domain-name "mydomain.com";
option domain-name-servers 192.168.1.2, 192.168.1.3;
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;
log-facility local7;

subnet 192.168.1.0 netmask 255.255.255.0 {
    option routers 192.168.1.1;
}
EOF
chkconfig dhcpd on
service dhcpd start
iptables -I INPUT -i eth0 -p udp --dport 67 --sport 68 -j ACCEPT
service iptables save

The /etc/dhcp/dhcpd.conf file will be changed every time we add a new host for network booting, so we will return to this. Note that you will need to turn off any existing DHCP server on your network. A lot of residential gateways have a DHCP server built-in. If your client is not getting the address that you expect, it is likely that there is another DHCP server on the network responding to the request.

Configuring the PXE Boot Server

Once the blank system has an IP address via DHCP, it will query the PXE boot server for a kernel. A PXE boot server services these request using a TFTP server. Configuring the PXE boot server is a one-time event. You will not be able to complete configuration of the PXE Boot Server until you have downloaded the os section of the distribution, since we need to copy the kernel images from that location. You can alternatively copy the kernel images from the minimal install CD.

cd /var/lib/tftpboot
cp /usr/share/syslinux/pxelinux.0 .
cp /usr/share/syslinux/menu.c32 .
mkdir -p pxelinux.cfg centos/i386 centos/x86_64
CENTOS=/var/www/html/centos/6/os
cp $CENTOS/i386/images/pxeboot/* centos/i386
cp $CENTOS/x86_64/images/pxeboot/* centos/x86_64
iptables -I INPUT -i eth0 -m state --state NEW -m tcp -p tcp --dport 69 -j ACCEPT
iptables -I INPUT -i eth0 -m udp -p udp --dport 69 -j ACCEPT
service iptables save
chkconfig tftp on
service xinetd restart

Once the blank system boots, you will be presented with a menu that allows you to pick what sort of system (32-bit or 64-bit) to install. I make you select something just in case the normal boot loader gets fried and you network boot by accident. By providing a menu, you can abort the network install before it formats your hard drives. The following implements my preferred menu structure:

cat <<EOF >pxelinux.cfg/default
DEFAULT menu.c32
PROMPT 0
TIMEOUT 300
ONTIMEOUT localdisk
MENU TITLE PXE Network Boot

LABEL localdisk
    MENU LABEL ^Local Hard Drive
    MENU DEFAULT
    LOCALBOOT 0

LABEL install_32bit
    MENU LABEL ^CentOS 6.0 (32-bit) Install
    KERNEL centos/i386/vmlinuz
    APPEND ks=http://NETINSTALL-HOST/ks/b32.ks initrd=centos/i386/initrd.img ramdisk_size=100000

LABEL install_64bit
    MENU LABEL ^CentOS 6.0 (64-bit) Install
    KERNEL centos/x86_64/vmlinuz
    APPEND ks=http://NETINSTALL-HOST/ks/b64.ks initrd=centos/x86_64/initrd.img ramdisk_size=100000
EOF

Replace the NETINSTALL-HOST with the DNS name of your Network Install Server in this configuration file. There are separate menu items for 32-bit and 64-bit systems because there are separate distributions, kernels and initial ram disks.

Note that you can make the process fully automated so that you don't even have to press a key before booting. However, the configuration requires you know things about the blank server that you can only find out by turning the machine on anyway, so I judge this a waste of time to configure.

Configuring Your Network Install

The final step in the process before we can actually get to installing our first blank server is to create a Kickstart file. Kickstart files provide the information necessary to install the system - any time you answer a question on the standard install, there is a kickstart equivalent command. Firstly, let's configure an area on our web server for serving the kickstart files to our clients.

mkdir /var/www/html/ks
cd /var/www/html/ks

We have to create a file called "b32.ks" in this directory. Here is mine:

cat <<EOF >b32.ks
install
url --url http://NETINSTALL-HOST/centos/6.0/i386
lang en_US.UTF-8
keyboard us
timezone --utc America/Denver
network --noipv6 --onboot=yes --bootproto dhcp
authconfig --enableshadow --enablemd5
rootpw --iscrypted CHANGEME
firewall --enabled --port 22:tcp
selinux --permissive
bootloader --location=mbr --driveorder=sda --append="crashkernel=auth rhgb"

# Disk Partitioning
clearpart --all --initlabel --drives=sda
part /boot --fstype=ext4 --size=200
part pv.1 --grow --size=1
volgroup vg1 --pesize=4096 pv.1

logvol / --fstype=ext4 --name=lv001 --vgname=vg1 --size=6000
logvol /var --fstype=ext4 --name=lv002 --vgname=vg1 --grow --size=1
logvol swap --name=lv003 --vgname=vg1 --size=2048
# END of Disk Partitioning

# Make sure we reboot into the new system when we are finished
reboot

# Package Selection
%packages --nobase --excludedocs
@core
-*firmware
-iscsi*
-fcoe*
-b43-openfwwf
kernel-firmware
-efibootmgr
wget
sudo
perl

%pre

%post --log=/root/install-post.log
(
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

# PLACE YOUR POST DIRECTIVES HERE
) 2>&1 >/root/install-post-sh.log
EOF

There are a couple of changes that will be required here. You can get the encrypted version of your root password with the following command:

grep 'root' /etc/shadow | awk -F: '{print $2}'

Insert this into the kickstart file at the appropriate point. Change NETINSTALL-HOST to the DNS name of your Network Install Server.

Optionally, you should consider the following:

In the %post section, you can add any shell script you wish to run. A few examples are provided below.

You can create the 64-bit version from the 32-bit version of the kickstart file. Remember to do this whenever you change the 32-bit file.

sed 's/i386/x86_64/g' b32.ks > b64.ks

Converting to a Static IP

All my servers run with a static IP. The following will convert the DHCP scope to a static IP with the same IP address.

echo "Converting DHCP scope to static IP address"

DEVICE=`route -n|grep '^0.0.0.0'|awk '{print $8}'`
IPADDR=`ifconfig $DEVICE|grep 'inet addr:'|awk '{sub(/addr:/,""); print $2}'`
NETMASK=`ifconfig $DEVICE|grep 'Mask'|awk '{sub(/Mask:/,""); print $4}'`
NETWORK=`ipcalc $IPADDR -n $NETMASK|awk -F= '{print $2}'`
GATEWAY=`route -n|grep '^0.0.0.0'|awk '{print $2}'`
HWADDR=`ifconfig $DEVICE|grep 'HWaddr'|awk '{print $5}'`

cat <<EOF >/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=$HOSTNAME
GATEWAY=$GATEWAY
EOF

cat <<EOF >/etc/sysconfig/network-scripts/ifcfg-$DEVICE
DEVICE=$DEVICE
BOOTPROTO=static
IPADDR=$IPADDR
NETMASK=$NETMASK
ONBOOT=yes
HWADDR=$HWADDR
EOF

Updating YUM to use Local Repository

We can place the conversion of the CentOS-Base.repo in our script as well.

echo "Updating YUM Repositories"
cd /etc/yum.repos.d
perl -npe '/mirrorlist=.*repo=os/ && s/^/#/' -i /etc/yum.repos.d/CentOS-Base.repo
perl -npe '/mirrorlist=.*repo=updates/ && s/^/#/' -i /etc/yum.repos.d/CentOS-Base.repo
perl -npe '/^#baseurl=.*\/os\// && s/^#//' -i CentOS-Base.repo
perl -npe '/^#baseurl=.*\/updates\// && s/^#//' -i CentOS-Base.repo
perl -npe '/^baseurl/ && s/mirror.centos.org/NETINSTALL-HOST/' -i CentOS-Base.repo
yum -y update

Installing a new sudoers List

I place a sudoers file in /var/www/html/ks/sudoers that can be installed on my system. This is best done with centralized authentication and centralized NFS-mounted home directories in place.

echo "Updating sudoers"
wget -O /etc/sudoers http://NETINSTALL-HOST/ks/sudoers
chmod 0440 /etc/sudoers
chown root.root /etc/sudoers

Configuring LDAP authentication

If you are using OpenLDAP as your authentication scheme, then you will want this to be linked during the installation.

echo "Configuring LDAP Authentication"
authconfig --enableldap --enableldapauth --ldapserver=ldap://ldap:389/ --ldapbasedn="dc=mydomain,dc=com" --enablecache --disablefingerprint --kickstart

Remember to add the following packages to the %packages list:

Configuring AUTOFS via LDAP

Closely related, if you are using OpenLDAP-based maps in LDAP, then you will want to configure that.

echo "Configuring autofs"
perl -npe 's/^automount:.*/automount: ldap/' -i /etc/nsswitch.conf
cat <<EOF >>/etc/sysconfig/autofs
LDAP_URI="ldap://ldap.mobilenimbus.com:389/"
SEARCH_BASE="ou=Maps,dc=mobilenimbus,dc=com"
MAP_OBJECT_CLASS="nisMap"
ENTRY_OBJECT_CLASS="nisObject"
MAP_ATTRIBUTE="nisMapName"
ENTRY_ATTRIBUTE="cn"
EOF

echo "Configuring LDAP autofs Boot-time"
chkconfig nscd on
chkconfig autofs on

Remember to add the following packages to %packages:

Preparing the Network Install Server for a Client

The final step before actually booting your client is to configure the DHCP server for providing a static IP address. To do this, use the following:

cat <<EOF >>/etc/dhcp/dhcpd.conf
host newserver {
    hardware ethernet ETHERNET-ADDRESS;
    fixed-address 192.168.1.10;
    filename "pxelinux.0";
}
EOF
service dhcpd restart

If you are using VMware ESXi, you can specify the ETHERNET-ADDRESS by editing the NIC specification. Otherwise, place the ethernet address in the appropriate place. An ethernet address is of the form XX:XX:XX:XX:XX:XX (6 groups of two hex digits). Also, ensure the name "newserver" is replaced by the DNS name of your server.

Once this is done, you can boot the server. The console of the blank server will eventually show the PXE Network Boot menu, allowing you to select either the 32-bit and 64-bit install. Once that is done, you should not have to do anything else until the server is ready.

Troubleshooting

Specific problems are listed below:

HowTos/NetworkInstallServer (last edited 2014-07-24 23:25:08 by TimothyLee)