<?xml version="1.0" encoding="utf-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Fun with ones and zeros - pxe</title>
<subtitle>Barry&#039;s notes on computer software and hardware</subtitle>
<link href="/blog/tags/pxe"></link>
<updated>2026-05-06T13:02:29-07:00</updated>
<id>urn:uuid:52d1c98e-1909-0bf2-b272-e8665af7bfe3</id>
<entry>
<title>iPXE on OpenBSD</title>
<link href="/blog/entries/ipxe-openbsd"></link>
<id>urn:uuid:edbadb7b-dc08-0bb7-4590-2fdf43a38f66</id>
<updated>2011-10-01T17:46:00-07:00</updated>
<author><name>Barry Pederson</name>
<email>bp@barryp.org</email>
</author>
<content type="html">&lt;p&gt;I got a chance to try &lt;a href=&quot;/blog/entries/enhanced-pxe-booting-ipxe/&quot;&gt;Enhanced PXE booting with iPXE&lt;/a&gt; on an OpenBSD box and found a couple things that &lt;em&gt;don&#039;t&lt;/em&gt; work...&lt;/p&gt;
&lt;p&gt;Firstly the stock DHCP daemon does not support &lt;code&gt;if&lt;/code&gt; statements in the configuration, so this bit to keep iPXE from being told to load iPXE (a loop) didn&#039;t work&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if exists user-class and option user-class = &quot;iPXE&quot; {
    filename &quot;http://10.0.0.1/pxelinux.0&quot;;
    } 
else {
    filename &quot;undionly.kpxe&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get it to work I had to follow the alternate advice on the &lt;a href=&quot;http://ipxe.org/howto/chainloading&quot;&gt;chainloading&lt;/a&gt; documentation about &lt;strong&gt;Breaking the loop with an embedded script&lt;/strong&gt;.  &lt;/p&gt;
&lt;p&gt;However, recompiling &lt;code&gt;udnionly.kpxe&lt;/code&gt; on OpenBSD 4.9 failed, with the error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;net/fcels.c: In function &#039;fc_els_prli_detect&#039;:
net/fcels.c:1108: internal compiler error: Segmentation fault: 11
Please submit a full bug report,
with preprocessed source if appropriate.
See &amp;lt;URL:http://gcc.gnu.org/bugs.html&amp;gt; for instructions.
gmake: *** [bin/fcels.o] Error 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(this was GCC 4.2.1).  FreeBSD 8.2 also has the same version of GCC and comes up with the same error.&lt;/p&gt;
&lt;p&gt;I ended up using an Ubuntu 10.04.3 box, which I believe was GCC 4.4.x, and that worked fine.&lt;/p&gt;</content>
</entry>
<entry>
<title>Enhanced PXE booting with iPXE</title>
<link href="/blog/entries/enhanced-pxe-booting-ipxe"></link>
<id>urn:uuid:19111ea9-dbf1-fd20-f5af-3ba2da89f737</id>
<updated>2011-09-22T06:00:00-07:00</updated>
<author><name>Barry Pederson</name>
<email>bp@barryp.org</email>
</author>
<content type="html">&lt;p&gt;While doing more reading on PXE as a followup to &lt;a href=&quot;/blog/entries/setting-pxe-environment-os-installations/&quot;&gt;Setting up a PXE
environment for OS installations&lt;/a&gt;, I ran into &lt;a href=&quot;http://ipxe.org/&quot;&gt;iPXE&lt;/a&gt;,
which has some interesting features which can simplify PXE booting.  The
main feature that caught my interest was HTTP support - meaning it can
fetch various modules, kernels, etc from a web server, which in general
is much more customizable and configurable than stock TFTP servers, and
also much faster.&lt;/p&gt;
&lt;p&gt;It took a while to figure out where it all fits into a boot stack, I
thought I&#039;d share what I&#039;ve roughly figured out and gotten to work.  &lt;/p&gt;
&lt;h2&gt;Stock PXE - a review&lt;/h2&gt;
&lt;p&gt;This diagram shows where we ended previously &lt;a href=&quot;/blog/entries/setting-pxe-environment-os-installations/&quot;&gt;previously&lt;/a&gt; with
installing Ubuntu over a network:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/11/24/stock_pxe.png&quot; alt=&quot;Stock PXE stack&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The PXE stack would obtain from a DHCP server the IP address of a TFTP
server and the name of a Network Boot Program (NBP) such as &lt;code&gt;pxelinux.0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pxelinux.0&lt;/code&gt; would then fetch a config file, and the config file fetched
a menu module.  Depending on what was selected from the menu, a Linux
kernel and initrd could be fetched and booted, and then the Ubuntu
installer presumably in the initrd would fetch additional install
packages from an HTTP server.&lt;/p&gt;
&lt;p&gt;Let&#039;s see what iPXE can do for us.&lt;/p&gt;
&lt;h2&gt;iPXE - replacement ROM&lt;/h2&gt;
&lt;p&gt;I didn&#039;t actually try this because it doesn&#039;t seem practical on a large
scale, but you can on many NICs &lt;a href=&quot;http://ipxe.org/howto/romburning&quot;&gt;replace the stock PXE ROM with iPXE&lt;/a&gt;,
giving you an arrangement like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/11/25/ipxe_rom.png&quot; alt=&quot;iPXE ROM&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A few things to note here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We can now use HTTP to load our NBPs - it&#039;s just a matter of changing
the DHCP config to say something like:
&lt;code&gt;filename &quot;http://10.0.0.1/whatever&quot;;&lt;/code&gt; &lt;em&gt;(the &lt;code&gt;next-server&lt;/code&gt; clause in the DHCP
config doesn&#039;t really matter now)&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can use the same NBPs such as PXELINUX that worked in the stock
PXE setup.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There&#039;s now an interactive console that lets you manually change settings
and load modules including Linux kernels and ramdisks directly - so iPXE is
also a  bootloader itself and you don&#039;t necessarily need something like
PXELINUX.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The same commands you can use interactively can be saved in script files,
so essentially it&#039;s like having a NBP that&#039;s a text file instead of having
to be a compiled binary.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I mentioned, I don&#039;t think it&#039;s practical to go around flashing various
NICs and motherboards, but there&#039;s another way to use iPXE....&lt;/p&gt;
&lt;h2&gt;Booting iPXE with PXE&lt;/h2&gt;
&lt;p&gt;There&#039;s a version of iPXE that can be &lt;a href=&quot;http://ipxe.org/howto/chainloading&quot;&gt;chainloaded&lt;/a&gt;, so that
you&#039;re using the stock PXE on your machine to bring in the enhanced iPXE
stack.  Here&#039;s the big picture first:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/11/26/ipxe_chain.png&quot; alt=&quot;PXE-&amp;gt;iPXE&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One of the APIs a PXE stack makes available is &lt;a href=&quot;http://en.wikipedia.org/wiki/Universal_Network_Device_Interface&quot;&gt;UNDI&lt;/a&gt;
(Universal Network Device Interface), giving a simple device driver
for the NIC that an NBP can use.  We can configure DHCP to load
&lt;a href=&quot;http://boot.ipxe.org/undionly.kpxe&quot;&gt;&lt;code&gt;undionly.kpxe&lt;/code&gt;&lt;/a&gt; as our initial NBP, it will use the UNDI part
of the stock PXE ROM (so it doesn&#039;t need to be configured for any
particular NIC), and it will start the PXE cycle again &lt;em&gt;(querying the DHCP
server for an IP address, the name of an NBP, etc...)&lt;/em&gt;, but with all the
extra features of iPXE available.&lt;/p&gt;
&lt;p&gt;We need to use a bit of logic in the DHCP config so that the iPXE stack
isn&#039;t also told to load &lt;code&gt;undionly.kpxe&lt;/code&gt; (basically causing a loop). This
can be done in ISC dhcpd with an &lt;code&gt;if&lt;/code&gt; statement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if exists user-class and option user-class = &quot;iPXE&quot; {
    filename &quot;http://10.0.0.1/pxelinux.0&quot;;
    } 
else {
    filename &quot;undionly.kpxe&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So that plain PXE is told to (TFTP) load &lt;code&gt;undionly.kpxe&lt;/code&gt; and iPXE is told
to load &lt;code&gt;http://10.0.0.1/pxelinux.0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;One cool thing about this setup is that we only need to make &lt;strong&gt;one&lt;/strong&gt; file
available through TFTP, &lt;code&gt;undionly.kpxe&lt;/code&gt;.  Everything else can be served up
by an HTTP server like Nginx.  This is great because HTTP servers are
generally more configurable than a stock TFTP server, plus you aren&#039;t
limited to serving up static files - some of these requests from iPXE could
be handled by CGI scripts or other webapps for more of a dynamic behavior.&lt;/p&gt;
&lt;h2&gt;PXELINUX on iPXE&lt;/h2&gt;
&lt;p&gt;If iPXE is the active PXE stack, then PXELINUX gains the ability to use
HTTP urls for module names, for example, an Ubuntu install might point
directly into a mounted ISO image shared on the web like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LABEL ubuntu-11.04-server-amd64-install             
    MENU LABEL Ubuntu 11.04 Server AMD64 Install
    kernel http://10.0.0.1/ubuntu-11.04-server-amd64/install/netboot/ubuntu-installer/amd64/linux
    append vga=788 initrd=http://10.0.0.1/ubuntu-11.04-server-amd64/install/netboot/ubuntu-installer/amd64/initrd.gz url=http://10.0.0.1/ubuntu-11.04-server-amd64.txt&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So, drop iPXE&#039;s &lt;a href=&quot;http://boot.ipxe.org/undionly.kpxe&quot;&gt;&lt;code&gt;undionly.kpxe&lt;/code&gt;&lt;/a&gt; into your TFTP server,
configure DHCP to give it out as an NBP only if a non-iPXE stack is asking,
and you can use HTTP for everything else.&lt;/p&gt;</content>
</entry>
<entry>
<title>Running MemTest86+ over PXE</title>
<link href="/blog/entries/running-memtest86-over-pxe"></link>
<id>urn:uuid:0ced6575-de9b-d1d3-5145-4c4c1e8f9236</id>
<updated>2011-09-05T09:36:00-07:00</updated>
<author><name>Barry Pederson</name>
<email>bp@barryp.org</email>
</author>
<content type="html">&lt;p&gt;Previously, we looked at &lt;a href=&quot;/blog/entries/setting-pxe-environment-os-installations/&quot;&gt;Setting up a PXE environment for OS
installations&lt;/a&gt;.  This post will build on that by adding
the &lt;a href=&quot;http://www.memtest.org/&quot;&gt;MemTest86+&lt;/a&gt; to the PXE environment, so you can easily run
memory checks on network-connected machines.&lt;/p&gt;
&lt;p&gt;This will be a really easy one.  First, download the MemTest86+ binary
into your &lt;code&gt;/tftpboot&lt;/code&gt; directory and decompress it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tftpboot
fetch http://www.memtest.org/download/4.20/memtest86+-4.20.bin.gz
gzip -d memtest86+-4.20.bin.gz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit the &lt;code&gt;/tftpboot/pxelinux.cfg/default&lt;/code&gt; file to add this menu entry
for MemTest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LABEL memtest86plus
    MENU LABEL MemTest86+ 4.20
    linux memtest86+-4.20.bin&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#039;s it, you should now be able to run MemTest over the network.&lt;/p&gt;
&lt;h2&gt;PXELINUX File Extensions&lt;/h2&gt;
&lt;p&gt;One extra thing to point out in case you&#039;re interested...&lt;/p&gt;
&lt;p&gt;The PXELINUX menu entry above says &lt;code&gt;linux memtest86+-4.20.bin&lt;/code&gt; instead of
&lt;code&gt;kernel memtest86+-4.20.bin&lt;/code&gt;  because when you use the &lt;code&gt;kernel&lt;/code&gt; keyword,
PXELINUX looks at the file extension &#039;.bin&#039; and treats the file like a CD
boot sector (which it is not in this case).  When I tried &lt;code&gt;kernel&lt;/code&gt; I just
got a stream of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;8200
8200
8200&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;on the screen over and over.   Alternatively, you could rename the MemTest
file to something without the &lt;code&gt;.bin&lt;/code&gt; extension, such as &lt;code&gt;memtest86p420&lt;/code&gt; and
then say &lt;code&gt;kernel memtest86p420&lt;/code&gt; and it would work.&lt;/p&gt;
&lt;p&gt;The SYSLINUX wiki mentions this on the &lt;a href=&quot;http://www.syslinux.org/wiki/index.php?title=Common_Problems&amp;amp;redirect=no#Watch_the_name_of_your_kernel&quot;&gt;Common Problems&lt;/a&gt; page.&lt;/p&gt;</content>
</entry>
<entry>
<title>Setting up a PXE environment for OS installations</title>
<link href="/blog/entries/setting-pxe-environment-os-installations"></link>
<id>urn:uuid:eccbca8e-6d83-c5ee-e951-5d96211c4c7c</id>
<updated>2011-09-01T09:00:00-07:00</updated>
<author><name>Barry Pederson</name>
<email>bp@barryp.org</email>
</author>
<content type="html">&lt;p&gt;If you&#039;re fooling around with various OSes, installing them by
first burning CDs or DVDs gets to be a drag - and you end up with piles of old
discs that just go into a landfill.  Sure, there are rewritable disks,
but they wear out and get scratched eventually.  USB memsticks can be
painful too - sometimes difficult to create and with different BIOSes
having different levels of support.&lt;/p&gt;
&lt;p&gt;A slick way to go is to set yourself up to do &lt;a href=&quot;http://en.wikipedia.org/wiki/Preboot_Execution_Environment&quot;&gt;PXE&lt;/a&gt; (Preboot
eXecution Environment) installations over a network.  Most network cards
have had PXE support included for many years now.  If you have a
machine handy that can act as a simple server, you can have an
enviroment where you boot a machine, select the OS you want to install
from a menu, and everything will just be pulled over your local network.&lt;/p&gt;
&lt;p&gt;There are plenty of writeups on how to PXE install Ubuntu from an Ubuntu
server, or FreeBSD from a FreeBSD server - but to make things more
interesting and explicit I&#039;ll go cross-platform and talk about deploying
Ubuntu Server 11.04 from a FreeBSD 8.2 server, and try to make it general
enough so that later on we can add other OSes to the menu such as CentOS
or OpenBSD.&lt;/p&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;PXE booting a machine requires two basic services be present on your
network:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DHCP - to assign the booted machine an IP address and tell it what
&amp;quot;network bootstrap program&amp;quot; (NBP) to fetch from a TFTP server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TFTP (Trivial FTP - not to be confused with regular FTP)
serves up the initial boot files&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OSes such as Ubuntu or CentOS require a third service:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP Server - serves up the bulk of the OS install files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;PXELINUX&lt;/h2&gt;
&lt;p&gt;For the Network Bootstram Program, we&#039;ll use &lt;a href=&quot;http://www.syslinux.org/wiki/index.php/PXELINUX&quot;&gt;PXELINUX&lt;/a&gt;, which
is available as part of the &lt;a href=&quot;http://www.syslinux.org/&quot;&gt;SYSLINUX&lt;/a&gt; project. The name
SYSLINUX is a bit misleading in that it&#039;s not actually Linux, but rather
a collection of bootloaders that are often used with Linux, and capable
of loading other OSes as well.  Think of something more along the lines
of &lt;a href=&quot;http://www.gnu.org/software/grub/&quot;&gt;GRUB&lt;/a&gt;, than an actual Linux distro.&lt;/p&gt;
&lt;p&gt;To start off with, I&#039;ll create a &lt;code&gt;/tftpboot&lt;/code&gt; directory, download
&lt;code&gt;syslinux-4.04.tar.gz&lt;/code&gt; from &lt;a href=&quot;http://www.kernel.org/pub/linux/utils/boot/syslinux/&quot;&gt;here&lt;/a&gt;, extract and
copy two files we want:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /tftpboot
fetch http://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-4.04.tar.gz
tar xzvf syslinux-4.04.tar.gz
cp syslinux-4.04/core/pxelinux.0 /tftpboot
cp syslinux-4.04/com32/menu/menu.c32 /tftpboot&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#039;re done with the syslinux download now, so you could clean it up
if you want with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rm -rf syslinux-4.04*&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, create a configuration directory&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /tftpboot/pxelinux.cfg&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and in that directory create a file named &lt;code&gt;default&lt;/code&gt; with these initial
contents:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DEFAULT menu.c32
PROMPT 0
TIMEOUT 200                           

LABEL local                           
    MENU LABEL Local Boot
    LOCALBOOT 0                     &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That should be enough to get us a barebones menu when we PXE boot a
machine, with a single option to boot off the local harddisk (we&#039;ll get
to Ubuntu later).&lt;/p&gt;
&lt;h2&gt;Enable TFTP&lt;/h2&gt;
&lt;p&gt;TFTP is already included in FreeBSD, just need to make sure it&#039;s enabled.  &lt;/p&gt;
&lt;p&gt;In &lt;code&gt;/etc/inetd.conf&lt;/code&gt; make sure this line has the default &lt;code&gt;#&lt;/code&gt; removed from the
front (so it&#039;s not commented out)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tftp   dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;/etc/rc.conf&lt;/code&gt;, make sure inetd is enabled, adding if necessary:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;inetd_enable=&quot;YES&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depending on what you had to do above, start, or reload the inetd daemon
with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;service inetd start&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;service inetd reload&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check that the machine is now listing on UDP port 69&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sockstat | grep :69&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See if you can fetch the NBP using the &lt;code&gt;tftp&lt;/code&gt; utility (assuming your
server&#039;s IPv4 address on the network you&#039;ll be doing PXE boots is
&lt;code&gt;10.0.0.1&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
tftp 10.0.0.1
tftp&amp;gt; get /pxelinux.0
tftp&amp;gt; quit
rm pxelinux.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If it works you should have seen somthing like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Received 26443 bytes during 0.1 seconds in 53 blocks&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tweak DHCP Server&lt;/h2&gt;
&lt;p&gt;For this part I&#039;m assuming you&#039;re running an ISC dhcpd server (if not,
we&#039;ll have to cover that in another post).  You basically just need to
add two lines to &lt;code&gt;/usr/local/etc/dhcpd.conf&lt;/code&gt; telling a client what
server to use for TFTP and what NBP to fetch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;next-server 10.0.0.1;
filename &quot;/pxelinux.0&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On my server, I just wanted to do this on one particular subnet, so
there&#039;s a chunk that looks something like this now:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;subnet 10.0.0.0 netmask 255.255.255.0 
    {
    range 10.0.0.127 10.0.0.250;
    option routers 10.0.0.1;

    next-server 10.0.0.1;
    filename &quot;/pxelinux.0&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart dhcpd&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;service isc-dhcpd restart&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Give it a try&lt;/h2&gt;
&lt;p&gt;On your client machine, you may have to poke around in the BIOS to
enable PXE booting.  You&#039;ll have to figure out this part for yourself.
If you can select your Network Card as the boot device, and everything
else is working right, you should see a simple menu something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/8/19/success.jpg&quot; alt=&quot;Initial success&quot; /&gt;&lt;/p&gt;
&lt;p&gt;OK! we&#039;re at the &amp;quot;Hello World&amp;quot; stage, we know the client and server are
doing the bare minimum necessary for PXE to function at all.  Time to
move on to the good stuff.&lt;/p&gt;
&lt;h2&gt;Ubuntu Server 11.04&lt;/h2&gt;
&lt;p&gt;For this next step, I&#039;ll assume you&#039;ve downloaded an ISO into say
&lt;code&gt;/foo/ubuntu-11.04-server-amd64.iso&lt;/code&gt;  The specific version shouldn&#039;t matter too
much, so if you want to do 10.04 LTS or something else, it should all be
about the same.&lt;/p&gt;
&lt;p&gt;Mount the ISO image, so we can copy a couple files into &lt;code&gt;/tftpboot&lt;/code&gt; and
share the rest with a web server.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -P /iso_images/ubuntu-11.04-server-amd64
mount -t cd9660 /dev/`mdconfig -f /foo/ubuntu-11.04-server-amd64.iso` /iso_images/ubuntu-11.04-server-amd64
mkdir /tftpboot/ubuntu-11.04-server-amd64
cp /iso_images/ubuntu-11.04-server-amd64/install/netboot/ubuntu-installer/amd64/linux /tftpboot/ubuntu-11.04-server-amd64
cp /iso_images/ubuntu-11.04-server-amd64/install/netboot/ubuntu-installer/amd64/initrd.gz /tftpboot/ubuntu-11.04-server-amd64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now our &lt;code&gt;/tftpboot&lt;/code&gt; directory has these five files underneath it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pxelinux.0
pxelinux.cfg/default
menu.c32
ubuntu-11.04-server-amd64/linux
ubuntu-11.04-server-amd64/initrd.gz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To the &lt;code&gt;/tftpboot/pxelinux.cfg/default&lt;/code&gt; file append&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LABEL ubuntu-11.04-server-amd64-install             
    MENU LABEL Ubuntu 11.04 Server AMD64 Install
    kernel ubuntu-11.04-server-amd64/linux
    append vga=788 initrd=ubuntu-11.04-server-amd64/initrd.gz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Try PXE booting your client again, this time you&#039;ll have
&amp;quot;Ubuntu 11.04 Server AMD64 Install&amp;quot; as one of your choices, select that,
cross your fingers, and if all goes well in a few seconds you should see:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/8/20/ubuntu_start.jpg&quot; alt=&quot;Initial success&quot; /&gt;&lt;/p&gt;
&lt;p&gt;and you can go through and answer the initial questions about the install. &lt;/p&gt;
&lt;p&gt;If you&#039;re OK with pulling the bulk of the OS over the internet from the
official Ubuntu mirrors, it should work although it might be slow.
Since we have a nice server sitting on our LAN with a copy of the ISO,
we should setup to use that and do a much faster install.&lt;/p&gt;
&lt;h2&gt;Web Server&lt;/h2&gt;
&lt;p&gt;For this example, I&#039;ll assume &lt;code&gt;nginx&lt;/code&gt; has been installed as the webserver
(any one will do though, so if you&#039;ve already got apache installed - that&#039;ll
work fine too).&lt;/p&gt;
&lt;p&gt;The default nginx install uses &lt;code&gt;/usr/local/www/nginx&lt;/code&gt; as its docroot, lets
put a symlink to our mounted ISO image in there:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ln -s /iso_images/ubuntu-11.04-server-amd64 /usr/local/www/nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and also put in a minimal Debian Installer &amp;quot;preseed&amp;quot; file in there that&#039;ll
help things along by telling the installer to use our webserver for
the installation packages.  Create a text file named &lt;code&gt;/usr/local/www/nginx/ubuntu-11.04-server-amd64.txt&lt;/code&gt; with these contents:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;d-i mirror/country string manual
d-i mirror/http/hostname string 10.0.0.1
d-i mirror/http/directory string /ubuntu-11.04-server-amd64
d-i mirror/http/proxy string&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check that you can fetch that file with the URL: &lt;code&gt;http://10.0.0.1/ubuntu-11.04-server-amd64.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Edit the &lt;code&gt;/tftpboot/pxelinux.cfg/default&lt;/code&gt; file and append&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;url=http://10.66.0.1/ubuntu-11.04-server-amd64.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the end of the &lt;code&gt;append&lt;/code&gt; line of our Ubuntu section, so it now looks like:    &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LABEL ubuntu-11.04-server-amd64-install             
    MENU LABEL Ubuntu 11.04 Server AMD64 Install
    kernel ubuntu-11.04-server-amd64/linux
    append vga=788 initrd=ubuntu-11.04-server-amd64/initrd.gz url=http://10.66.0.1/ubuntu-11.04-server-amd64.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Try PXE booting the Ubuntu install again.  You&#039;ll still get some initial
questions about language and keyboard (we can deal with those in another
post), but you shouldn&#039;t be asked about mirrors - the installer will know to
pull files from your local webserver. &lt;/p&gt;
&lt;p&gt;Go through the install on the client, watch the &lt;code&gt;/var/log/nginx-access.log&lt;/code&gt;
file on the server, you&#039;ll see the installer fetching all kinds of files,
so you&#039;ll know it&#039;s all working.&lt;/p&gt;
&lt;h2&gt;You&#039;re in business&lt;/h2&gt;
&lt;p&gt;So at this point you&#039;ve got yourself a working PXE installation environment
and can do a basic Ubuntu server install.  &lt;/p&gt;
&lt;p&gt;By adding a few more parameters to your seed file and the PXE
configuration you can eliminate some of the installer questions.  I&#039;ll
probably write about that in another post, but if you want to figure it
out yourself, check out the &lt;em&gt;Ubuntu Installation Guide&lt;/em&gt; - &lt;a href=&quot;https://help.ubuntu.com/11.04/installation-guide/amd64/appendix-preseed.html&quot;&gt;Appendix B. Automating the installation using preseeding&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There&#039;s so many things you can do with the PXE menus, kernel options, and so
on - it can&#039;t all be covered in one place.  But hopefully you&#039;ve got a good
starting point now, if you know all the basic services are in place and
working.  &lt;/p&gt;</content>
</entry>
</feed>