Setting up a CentOS 7 PXE server

PXE (or Pixie) boot is a very convenient way to start machines by providing custom operative systems trough the network.

Furthermore, in this post I will also explain how to set up a kickstarter file to perform a fully unatended CentOS 7 installation.

The idea is very simple: a machine with PXE boot enabled will boot up and search for a PXE enabled DHCP server on it’s network, and when found, it will request an IP and network configuration. Together with this network configuration, it will receive some booting instructions including the “iso” file of the operative system which is going to boot.

The operative system is provided by a simple ftp (or tftp) server, and if we provide a kickstart file we can automate the whole installation process without the need of any interaction with the computer.

I am going to explain how to install one of this servers in Centos 7 with a self explaining script, based on the guide in unixmen.com.

Ok, first of all, if you happen to be experimenting with KVM, you should create an isolated network without DHCP, by


cat > xmlnetfile << EOF
<network connections='2'>
<name>pxenet</name>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr5' stp='on' delay='0'/>
<mac address='52:54:00:72:ed:de'/>
<ip address='10.0.8.1' netmask='255.255.255.0'>
</ip>
</network>
EOF

virsh net-create xmlnetfile

That creates the network 10.0.8.0/24 without DHCP in the interface virtbr5 (if it doesn’t exist it will create it.

Now, we need to install a minimal CentOS (7) on a virtual machine on this network, with a virtual hard disk of at least 5 Gb.
You can either click on the virtual machine manager, or just copy and paste:


# Create a raw virtual hard disk, which is basically a file full of zeros
dd if=/dev/zero of=/var/lib/libvirt/images/pxe-server.img bs=1M count=5000
# You can also create a qcow2 file, which saves space but is slower
#qemu-img create -f qcow2 /var/lib/libvirt/images/pxe-server.qcow2 8192

# Download the iso of the operative system you want to install
wget http://mirror.skylink-datacenter.de/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1503-01.iso .

# Launch the installer
virt-install -r 8192 --accelerate -n pxe-server --os-type=linux --os-variant=rhel6 -f /var/lib/libvirt/images/pxe-server.img --vnc --force --network network=pxenet --vcpus=4 --cdrom CentOS-7-x86_64-Minimal-1503-01.iso

… and just follow the prompts for a normal installation. Set up the IP to be 10.0.8.5, netmask 255.255.255.0 and gateway 10.0.8.1.

While the installer finishes copying the files, I will clear that I consider myself a “Debian” or at least “Ubuntu” kind of person, and that reason use CentOS is purely due to company policies.

Well… Once everything is installed and rebooted, proceed as follows:


# Install packages
sudo su
yum -y install dhcp tftp tftp-server syslinux wget vsftpd

cat > /etc/dhcp/dhcpd.conf << EOF 
# DHCP Server Configuration file. 
# see /usr/share/doc/dhcp*/dhcpd.conf.example 
# see dhcpd.conf(5) man page 
# 
# option definitions common to all supported networks... 
ddns-update-style interim; ignore client-updates; 
authoritative; allow booting; 
allow bootp; 
allow unknown-clients; 
# A slightly different configuration for an internal subnet. 
subnet 10.0.8.0 netmask 255.255.255.0 { 
     range 10.0.8.100 10.0.8.200; 
     option domain-name-servers 10.0.8.6;  
     option routers 10.0.8.1; 
     default-lease-time 600; 
     max-lease-time 7200; 
     # PXE SERVER IP 
     next-server 10.0.8.5; # DHCP server ip 
     filename "pxelinux.0"; 
     } 
EOF 

cat > /etc/xinetd.d/tftp << EOF
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /var/lib/tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
EOF

# Make sure the directory exists and has the right permissions
mkdir -p /var/lib/tftpboot
chmod 777 /var/lib/tftpboot

cp -v /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot
cp -v /usr/share/syslinux/menu.c32 /var/lib/tftpboot
cp -v /usr/share/syslinux/memdisk /var/lib/tftpboot
cp -v /usr/share/syslinux/mboot.c32 /var/lib/tftpboot
cp -v /usr/share/syslinux/chain.c32 /var/lib/tftpboot

mkdir /var/lib/tftpboot/pxelinux.cfg
mkdir -p /var/lib/tftpboot/netboot/

# Find an operative system image, for example:
# wget http://ftp.fau.de/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1503-01.iso .

# Mount the ISO file and copy the kernel and initial scripts
mkdir /mnt/iso
mount CentOS-7-x86_64-Minimal-*.iso /mnt/iso 
cp -r /mnt/iso/* /var/ftp/pub/ 

cp /var/ftp/pub/images/pxeboot/vmlinuz /var/lib/tftpboot/netboot/ 
cp /var/ftp/pub/images/pxeboot/initrd.img /var/lib/tftpboot/netboot/ 

Now we create a kickstart file for the unattended installation of CentOS:


PASSWORD=$(openssl passwd -1 "YOUR_PASSWORD")

cat > /var/ftp/pub/ks.cfg << EOF

# System authorization information
auth --enableshadow --passalgo=sha512
# System authorization information
auth useshadow passalgo=sha512

# Firewall configuration
firewall --disabled
# Install OS instead of upgrade
install
# Use NFS installation media
url --url="ftp://10.0.8.5/pub/"

# Root password
#Those hashes are generated with:
# openssl passwd -1 1234
rootpw --iscrypted $1$H3CXrcOE$NoWDbJnH7dj8UpVoN5FG..

# System timezone
timezone Europe/Berlin --isUtc
user --name=user --password=$1$H3CXrcOE$NoWDbJnH7dj8UpVoN5FG.. --iscrypted --gecos="User"

# Use text or graphical install
graphical
firstboot disable
# System keyboard
keyboard us
# System language
lang en_US.UTF-8 --addsupport=de_DE.UTF-8

# SELinux configuration
selinux disabled
# Installation logging level
logging level=info

# System bootloader configuration
bootloader location=mbr
clearpart --all --initlabel
part swap --asprimary --fstype="swap" --size=1024
part /boot --fstype xfs --size=200
part pv.01 --size=1 --grow
volgroup rootvg01 pv.01
logvol / --fstype xfs --name=lv01 --vgname=rootvg01 --size=1 --grow
# Partition clearing information
#clearpart --none --initlabel

#Reboot after installation?
reboot

# Network information
network --bootproto=static --device=eth0 --ip=10.0.8.45 --netmask=255.255.255.0 --gateway=10.0.8.1 --nameserver=10.0.8.1 --activate

network --hostname=testvm-pxebooted

%packages
@core
%end

%post
yum -y install wget net-tools vim
%end

EOF

Now just


cat > /var/lib/tftpboot/pxelinux.cfg/default << EOF
default menu.c32
prompt 0
timeout 30
MENU TITLE My PXE Menu

LABEL centos7_x64
MENU LABEL CentOS 7 X64
KERNEL /netboot/vmlinuz
APPEND initrd=/netboot/initrd.img inst.repo=ftp://10.0.8.5/pub ks=ftp://10.0.8.5/pub/ks.cfg
EOF

… and finish by:


# Run daemons on boot
chkconfig dhcpd on
chkconfig xinetd on
chkconfig vsftpd on

# Restart daemons
service vsftpd restart
service dhcpd restart
service xinetd restart

# Also turn off SELinux and the firewall
service firewalld stop
setenforce 0

And that’s it.

Now, just start a new virtual machine in the same network by clicking or just copy pasting

# Create a virtual machine called "testvm-pxebooted" with 8 Gb RAM, PXE booted, 4 CPUS and 4 GB of storage
virt-install -r 8192 --accelerate -n testvm-pxebooted --pxe --os-type=linux --os-variant=rhel6 -f /var/lib/libvirt/images/testvm-pxebooted.img --vnc --force --network network=pxenet --vcpus=4 -s 4000

… and enjoy looking at the CentOS 7 which installs itself 🙂

 

Here are some tips to help troubleshooting possible problems.

Number one, ensure that

service dhcpd status
service xinetd status
service vsftpd status

There should not be errors, otherwise double check the config files.

If there are no errors but the new machine doesn’t boot, check SELinux and the firewall are disabled.

A port scan shows this:

PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
25/tcp open smtp