Debian Wheezy PXE server

by on January 1, 2013 at 4:47 pm

Creating a PXE boot server is both easy and useful.  PXE boot services allow an administrator to install or boot an operating system dynamically every time a machine is booted.  This method is especially useful for imaging multiple servers in an automated fashion.

I’m writing this entry to outline the steps necessary to create a Debian server that provides DHCP and PXE boot services of multiple to specific hosts on the same network.

Requirements:  Debian Wheezy or other compatible server with plenty of free space, and an additional server/computer on the same network (or virtual network) as the Debian server.  If you’re using something other than Debian Wheezy, I can’t assure you the packages will be the same and configured the same way.  This is Linux, after all.

If you want an in-depth explanation of what we’re accomplishing here, please check this link on PXELINUX.

Step 1:  Configure network interface

My setup assumes you have 2 ethernet adapters.  eth0 is the interface your box has for public network access.  eth1 will be the interface we setup dhcp services on, the management network.

vi /etc/network/interfaces

Add the following:

auto eth1
iface eth1 inet static

Now we need to bring up that interface:  ifup eth1

It may throw an error, but that’s okay.  We should how be able to see eth1 with an ip assigned in the output of the command ifconfig and the interface should respond to ping.

Step 2:  Install necessary packages

apt-get install tftpd-hpa dhcp3-server syslinux

dhcp3-server will actually install isc-dhcp-server in Wheezy.

Optional:  apt-get install apache2

Installing apache2 (if not already installed on your server) will allow you to host the balance of the install files, otherwise you’ll have to use another source for your files.

Step 3:  Setup DHCP config file

This is the part where I ran into a small amount of trouble because each option wasn’t really described, and I found conflicting information.  This section is 100% tested by me and works on my system.

vi /etc/dhcp/dhcpd.conf

ddns-update-syle none;
allow booting;
allow bootp;

subnet netmask {
  option routers;
  option subnet-mask;
  #Range of IPs to dynamically assign.  Optional.
  default-lease-time 120;
  max-lease-time 120;
  #Next line should be whatever server hosts PXE files.

  #Uncomment next line for TFTP running in chrooted environment.
  filename "pxelinux.0";

  #Uncomment next line for TFTP running not in chroot environment.
  #filename "/var/lib/tftpboot/pxelinux.0";

#This next part is optional, see optional steps at the end of this article
  group {
    host new_host {
      hardware ethernet 00:00:00:00:00:00;
#end optional part


So, what we’ve done there is allow is setup a DHCP server to assign servers on the same broadcast domain an IP between and  This IP range is arbitrary.  It can be anything from .2 to .254 if you choose.

The line next-server; tells the booting computer where the PXE server is.  If there was another PXE server on the same network, you could change this IP to reflect that if you wish.  However, our PXE server will be the same as our DHCP server, thus the IP we setup earlier.

filename “pxelinux.0″; is required to point the booting computer to the right file.  This is the default file name for this service, and generally should remain the same.  The line allow booting; and allow bootp; instructs the dhcp service to provide PXE services.

Step 4:  Setup TFTP config file

This was another tricky area.  I’m not an expert on this service, but this is what I have in my config file, which is a compilation of various references below:

vi /etc/default/tftpd-hpa

#Comment the next line if you don\'t want to run in chroot environment.

We also need to make the directory we just referenced above:  mkdir /var/lib/tftpboot

Step 5:  Install PXE files, kernels, and initrd’s.

These files from syslinux will handle the initial booting of the target system, and serve as the components of the chain loader for loading our kernels.

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

Now, we also want to create the necessary directory structure.  Please note, the pxelinux.cfg directory is mandatory.  The other directories can be called whatever you wish.

mkdir /var/lib/tftpboot/pxelinux.cfg

mkdir /var/lib/tftpboot/images

mkdir /var/lib/tftpboot/images/deb

mkdir /var/lib/tftpboot/images/centos

Next, we want to download our kernel and initrd files.

cd /var/lib/tftpboot/images/deb

For our CentOS 6 installation, you will need to obtain an ISO or CD/DVD.  I’ll leave it up to you to decide where you want to get that from.

The files you need to copy are as follows:

cd /var/lib/tftpboot/images/centos
cp <dvd/iso>/images/pxeboot/initrd.img .
cp <dvd/iso>/images/pxeboot/vmlinuz .

The easiest way to obtain these files is to download an ISO from a torrent or mirror, and mount the ISO temporarily with the following command:

mount -o loop /path/to/centos.iso /mountpoint

Step 6:  Setup PXE menu

vi /var/lib/tftpboot/pxelinux.cfg/default

default menu.c32
prompt 0
timeout 300


LABEL Debian Wheezy x86
 MENU LABEL Debian Wheezy x86
 KERNEL images/deb/linux
 APPEND initrd=images/deb/initrd.gz

LABEL Centos 6
 MENU LABEL Centos 6
 KERNEL images/centos/vmlinuz
 APPEND initrd=images/centos/initrd.img askmethod

You’ll notice I included the ‘askmethod’ argument on the APPEND line for CentOS.  This is because the APPEND line will accept any kernel arguments you would normally pass as if you were booting from the install DVD.  Using askmethod allows you to select installation files from an NFS or other file source.

Debian’s default install DVD will fail by default with PXE boot, because the installation files aren’t available as local media.  However, we downloaded the kernel and initrd from their netboot install tree, which will allow us to download the necessary install files from any http/ftp network mirror we choose.  No special arguments are necessary.

Step 7:  Start services

I’m generally a proponent of using the ‘service’ command to start and stop services, but this is a rare care where I recommend otherwise because the service names are nonsensical, and running them from /etc/init.d/ allows you to use ‘tab’ to complete the line (if you’re in bash, anyway).

/etc/init.d/isc-dhcp-server restart

/etc/init.d/tftpd-hpa restart

Step 8:  Test it all out!

Well, this step should be self explanatory.  Simply add another host to the same network as your PXE server, and PXE boot it.  If everything went well, your screen should look something like this:


Optional Step 1: The complete picture

So, we’ve gone through the trouble of setting up our PXE server, but now we need a location to store the actual installation files.

If you chose to install apache in step 2, then you’re on the right track.  If you want to build a Debian private mirror, I have yet to do this, and I will differ you to reading this page:  Debian Mirror

For our CentOS installation, the process is quite easy.  If you have already obtained the installation ISO, that will serve as our package / installation repository as-is.  No need to modify.  Simply create a new folder called ‘centos’ in /var/www and mount the ISO there.  Start apache2 with (it’s generally started automatically on installation)

service apache2 start

Now, during your installation of CentOS, simply choose to install via HTTP with and everything should go smoothly.

Optional Step 2:  Limit which hosts can PXE Boot

For a number of reasons, you may want to limit which hosts on your network can PXE boot from you installation server.  My ideal setup is modeled around a production environment to disable dynamic assignment of IPs altogether.  To achieve this, we simply comment out the “range” line of /etc/dhcp/dhcpd.conf

Since an administrator is going to be overseeing which server is going to be built or rebuilt, it makes sense to limit the authorized systems by MAC address, as in this section from dhcpd.conf:

#This next part is optional, see optional steps at the end of this article
  group {
    host new_host {
      hardware ethernet 00:00:00:00:00:00;
#end optional part

As you can see, you can specific the exact MAC address that should be able to get an IP and thus PXE boot.  This will ensure that if a host needs to be added or rebuilt in a large production environment, you won’t accidentally image the wrong server.  In fact, I would keep the dhcp service off until needed as well, just to be safe.

Here are some helpful articles that I have read to put his all together (Some are additional further reading):


Debian Automated Install

in Debian, How-To

, , , , , ,

You can skip to the end and leave a response. Pinging is currently not allowed.

  • ben-Nabiy

    Very nice article. You just left out one little detail regarding the isc-dhcp-server.

    By default, the DHCP server does not assume to listen on any ethernet port. You need to edit /etc/default/isc-dhcp-server and set INTERFACES=”eth0″ or whatever interface (in the case of multiple network cards) you want the DHCP to listen for requests on. After changing this setting, you need to do a:
    sudo service isc-dhcp-server restart

    Then all should be well.

    • Mike

      Thank you for the tip!

  • Andre JavaLate

    Hi, I’m working in company where everybody uses Ubuntu or Mint.

    I’m thinking of setting up Debian PXE server with cobbler. I don’t know yet how exactly to do it but after reading serveral articles I understood that I need to install DHCP server as well and I’m affraid that it will conflict with DHCP server on GW router.

    Will these DHCP servers conflict with each other?

    • Mike

      Yes, they will conflict with each other. If the PXE server and GW are on the same LAN, then I would suggest turning off DHCP on the router, manually IPing the GW router to .1, manually IPing the PXE server to .2, and just use the PXE server for DHCP.

  • Andruss

    Please note:

    After making of mount -o on next server restart you need once again to mount iso.

    To mount automatically add to fstab.
    vim /etc/fstab

    /path/to/your_iso/Centos6.5-x86_64-minimal.iso /path/to/your/mountedfolder/centos6_x86_64 iso9660 loop 0 0

    save and quit.

    Then run mount -a

    • Mike

      Good tip, thank you.