HOWTO: Configure a CentOS 6.0 Network Install Server
1. 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:
- DHCP Server provides an IP Address to the blank server
- PXE Boot Server provides a kernel and boot environment to the blank server
- Distribution Server provides the CentOS distribution to the blank server
- Your own configuration tells the blank server what packages to install
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.
2. Before You Begin
2.1. 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:
- One processor
- 512Mb RAM
- 64Gb Disk partitioned with separate partitions:
- /boot - primary partition, 256Mb
- / - LVM, 6Gb
- /var/log - LVM, 4Gb
- swap - LVM - 1Gb
- /var/www - LVM, Rest of Disk
- Static IP Address Assigned
- "Minimal" ISO Install
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.
2.2. 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.
2.3. Entering Commands
All commands should be executed with "root" privileges on the Network Install Server. Refer to Becoming Root for more information.
2.4. 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.
3. Required Packages
The following will install all the required packages:
yum -y install rsync httpd vixie-cron dhcp tftp-server syslinux make perl
4. 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
5. 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.
6. 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.
7. 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.
8. 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:
- Disk partitioning. The recipe includes a fixed sized /boot and / partitions, plus a /var partition for the majority of the disk. This may not be appropriate for your situation.
SELinux and Firewalls. The recipe allows you to ssh to the host, and places SELinux in permissive mode. Refer to the Kickstart documentation for other arguments to both entries.
- Package Selection. The recipe has a very minimal package selection - expecting you to install any packages you need after the fact. I routinely add other diagnostic and utility packages (such as wget, bind-utils, telnet and openssh-clients) to the list.
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
8.1. 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
8.2. 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
8.3. 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
8.4. 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:
- openldap
- openldap-clients
- nss-pam-ldapd
- pam_ldap
8.5. 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:
- rpcbind
- nfs-utils
- nscd
- autofs
9. 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.
10. Troubleshooting
Specific problems are listed below:
- DHCP Address not received:
- Make sure the Firewall on the Network Install Server allows UDP packets from port 68 to port 67.
- Make sure the DHCP server is running
- Make sure there is no other DHCP server on the network
- TFTP Files not downloaded
- Make sure the Firewall on the Network Install Server allows UDP and TCP packets to port 69
- Make sure the TFTP server is running
- Install a tftp client and try to retrieve pxelinux.cfg/default
- Install asks where the distribution is
- Make sure the Firewall on the Network Install Server allows TCP port 80
- Make sure you can download the distribution files from the network install server
- Make sure the "url" statement in the kickstart file is correct
- Make sure the Network Install Server is registered in DNS
- Install asks other questions
- This is a problem in the kickstart file - find the appropriate section in the kickstart file