Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

PXE Boot for Automated OS Installs

By Kokil Thapa | Last reviewed: September 2026

Provisioning ten identical web servers by hand wastes hours and drifts configuration. PXE Boot for Automated OS Installs solves that by letting bare-metal machines fetch a boot loader over the network, pull a kernel and installer, and apply an unattended answer file. On production Linux system administration work—shared EC2 sister sites and client racks alike—the pattern mirrors what you already do with Git and Deployer: define the target state once, then repeat it reliably. This guide walks through a practical Ubuntu 24.04 LTS stack using dnsmasq, TFTP, and HTTP preseed files you can run on a single management host.

What is PXE boot and how does automated OS installation work?

PXE—Preboot eXecution Environment—extends the firmware boot path. The NIC broadcasts a DHCP discover packet. The DHCP server replies with an IP lease plus boot server and boot file names. The client downloads that file over TFTP, executes it, loads a Linux kernel and initrd, and starts the distribution installer.

The automation layer sits in the answer file. Debian and Ubuntu use preseed. Red Hat family uses kickstart. You declare locale, disk layout, packages, users, and post-install scripts. The installer never prompts. Every machine lands in the same baseline state.

That matters when you refresh hardware, rebuild a staging rack, or onboard a new VPS host colocated in Kathmandu next to your primary stack. Manual installs invite typos. PXE removes variance. It also pairs well with post-install tools like Ansible or cloud-init for application layers—topics adjacent to CI/CD caching for fast Composer and npm installs once PHP 8.3+ and Laravel 13.x runtimes are in place.

PXE Boot Chain OverviewUEFI / BIOSNIC PXE ROMDHCP ServerIP + bootfileTFTP Serverpxelinux / iPXEHTTP / NFSvmlinuz + initrdDebian-Installer / UbiquityReads preseed URL — zero promptsPost-Install HookSSH keys, hardening, Deployer user
PXE Boot for Automated OS Installs: firmware hands off to DHCP and TFTP, then the installer pulls preseed over HTTP.

Core protocols you must understand

  • DHCP — assigns IPv4 and tells the client where to fetch boot files via options 66 (next-server) and 67 (filename).
  • TFTP — small, UDP-based transfer for boot loaders; keep payloads tiny.
  • HTTP or NFS — serves large kernel, initrd, and ISO contents; HTTP is simpler on firewalled LANs.
  • Preseed / kickstart — declarative install answers consumed by the installer.

The original PXE spec builds on BOOTP, documented in RFC 951. Modern shops often chain into iPXE for HTTPS and scriptable menus. That flexibility beats legacy pxelinux when you juggle multiple Ubuntu LTS tracks.

How do you set up a PXE server on Ubuntu for automated installs?

A single management VM on your LAN can host every role. I prefer dnsmasq because it combines DHCP and TFTP in one daemon with a small config surface. Separate nginx or Apache serves HTTP assets. Isolate this host on a dedicated VLAN when possible.

Before you start, mirror the target release. For Ubuntu 24.04 LTS, sync the netboot mini.iso tree or extract linux and initrd.gz from the installer. Store checksums. Pin versions the same way you pin PHP 8.3 on application servers.

Step 1 — Install packages and create directory layout

  1. Install dnsmasq, nginx, and syslinux-common on Ubuntu 24.04.
  2. Create /srv/pxe/tftp for boot loaders and /srv/pxe/http for kernels, initrd, and preseed files.
  3. Copy pxelinux.0, ldlinux.c32, and menu modules from syslinux into the TFTP root.
sudo apt update
sudo apt install dnsmasq nginx syslinux-common pxelinux

sudo mkdir -p /srv/pxe/tftp/pxelinux.cfg
sudo mkdir -p /srv/pxe/http/ubuntu/noble/{amd64,preseed}

sudo cp /usr/lib/PXELINUX/pxelinux.0 /srv/pxe/tftp/
sudo cp /usr/lib/syslinux/modules/bios/ldlinux.c32 /srv/pxe/tftp/
sudo cp /usr/lib/syslinux/modules/bios/{menu.c32,libutil.c32} /srv/pxe/tftp/

Step 2 — Configure dnsmasq DHCP and TFTP

Bind dnsmasq only to your provisioning interface. Never run two DHCP servers on the same broadcast domain. That mistake blackholes laptops and printers.

# /etc/dnsmasq.d/pxe.conf
interface=eno1
bind-interfaces
dhcp-range=192.168.50.100,192.168.50.200,255.255.255.0,12h
dhcp-option=option:router,192.168.50.1
dhcp-boot=pxelinux.0,pxeserver,192.168.50.10
enable-tftp
tftp-root=/srv/pxe/tftp
log-dhcp

Restart and watch logs during a test boot:

sudo systemctl restart dnsmasq
sudo journalctl -u dnsmasq -f

Step 3 — Write pxelinux menu and nginx location

The default menu entry points the installer at your preseed URL. Use the auto=true kernel parameter for fully unattended mode.

# /srv/pxe/tftp/pxelinux.cfg/default
DEFAULT menu.c32
PROMPT 0
TIMEOUT 50
ONTIMEOUT ubuntu-noble-auto

LABEL ubuntu-noble-auto
    MENU LABEL Ubuntu 24.04 Unattended
    KERNEL http://192.168.50.10/ubuntu/noble/amd64/linux
    APPEND initrd=http://192.168.50.10/ubuntu/noble/amd64/initrd.gz \
      auto=true priority=critical \
      url=http://192.168.50.10/ubuntu/noble/preseed/noble.seed \
      netcfg/choose_method=auto \
      debian-installer/locale=en_US.UTF-8

Expose HTTP under nginx with directory listing disabled:

# /etc/nginx/sites-available/pxe
server {
    listen 80;
    server_name pxeserver.internal;
    root /srv/pxe/http;
    location / {
        autoindex off;
    }
}

Enable the site, test config, reload nginx—the same discipline as installing Nginx on Ubuntu for Laravel apps. Then place kernel artifacts under /srv/pxe/http/ubuntu/noble/amd64/.

PXE Lab TopologyPXE Management Hostdnsmasq + TFTP + nginx192.168.50.10Server ABare metalServer BBare metalServer CBare metalProvisioning VLAN 192.168.50.0/24No production traffic — firewall upstream
Dedicated VLAN keeps PXE DHCP scopes away from office Wi-Fi and production Laravel stacks.

Which preseed or kickstart configuration drives unattended installation?

Preseed files are plain text debconf answers. Order matters for early directives like locale and keyboard. Late commands run chrooted scripts—ideal for injecting SSH keys, disabling root login, or registering the host with your monitoring stack.

Minimal Ubuntu 24.04 preseed example

# /srv/pxe/http/ubuntu/noble/preseed/noble.seed
d-i debian-installer/locale string en_US.UTF-8
d-i keyboard-configuration/xkb-keymap select us
d-i netcfg/choose_interface select auto
d-i mirror/http/hostname string archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
d-i partman/confirm_write_new_label boolean true
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i pkgsel/include string openssh-server curl git ufw
d-i pkgsel/upgrade select full-upgrade
d-i grub-installer/only_debian boolean true
d-i user-setup/allow-password-weak boolean false
d-i passwd/user-fullname string Deploy User
d-i passwd/username string deploy
d-i passwd/user-password-crypted password $6$rounds=4096$...
d-i preseed/late_command string \
  in-target ufw --force enable; \
  in-target mkdir -p /home/deploy/.ssh; \
  in-target sh -c 'echo "ssh-ed25519 AAAA..." >> /home/deploy/.ssh/authorized_keys'

Generate password hashes with mkpasswd -m sha-512. Never store cleartext passwords in Git. For stronger secrets at scale, fetch short-lived tokens from your vault during late_command. The same hygiene applies when you rotate database credentials on MySQL servers on Ubuntu.

Official reference material lives in the Debian preseed documentation. Ubuntu inherits most directives unchanged.

Kickstart on RHEL-family hosts

If you standardise on Rocky or AlmaLinux, swap preseed for kickstart. Place inst.ks=http://pxeserver/kickstart/host.cfg on the kernel line. Partition with autopart or explicit part lines. %post scripts mirror late_command.

Post-install alignment with application stacks

After the OS lands, layer runtimes. Install PHP 8.3, Composer 2.10, and MySQL 8.4 LTS using your existing playbooks. Sites on shared Deployer pipelines—like the legal-tech sister properties described in my Translation Nepal portfolio case—benefit from identical PHP-FPM pools across nodes. PXE gives you that parity on day zero.

Manual vs PXE DecisionHow many servers?1–2 hostsUSB is fine3+ hostsPXE winsUSB pathHand click each screenPXE pathIsolated VLANVersioned ISO hash
Choose PXE Boot for Automated OS Installs when repeatability and audit trails matter more than one-off convenience.

How does PXE compare to USB installs, cloud images, and MAAS?

PXE is not the only automation path. Pick based on hardware access, cloud mix, and team skill. The table below summarises trade-offs I use when scoping enterprise application deployments.

MethodBest forProsCons
USB / manual1–2 machines, laptopsSimple, no infraSlow, inconsistent
PXE + preseedOn-prem racks, coloFast repeat, low costNeeds VLAN discipline
Cloud vendor imagesAWS, GCP, Azure VMsAPI-driven, elasticVendor lock-in facets
Canonical MAASLarge bare-metal fleetsInventory, IPAM, UIHeavier ops overhead
Immutable images (Packer)Hybrid cloud + metalGolden AMI QCOW2Build pipeline required

For Nepali SMB clients with a single Dell tower running WooCommerce 11.1, USB still wins. For a three-node cluster serving Laravel queues and Redis 8.10, PXE pays back after the second rebuild. Hybrid shops boot PXE on metal and cloud-init on VMs—both feed the same Ansible roles.

Cloud-init overlaps conceptually but targets hypervisor metadata services, not legacy BIOS PXE ROMs. Treat them as complementary layers in a support and maintenance playbook rather than competing religions.

What are common PXE boot failures and how do you fix them?

Most PXE outages are DHCP scope collisions, wrong boot filenames, or firmware mode mismatches. Work top-down: link light, DHCP log, TFTP transfer, then HTTP 200 on kernel URLs.

Failure checklist

  • No DHCP offer — second DHCP server on VLAN; bind dnsmasq to one interface; disable rogue router DHCP.
  • TFTP timeout — file permissions on /srv/pxe/tftp; SELinux/AppArmor denials; firewall blocking UDP 69.
  • Boot hangs after menu — BIOS vs UEFI mismatch; use syslinux for BIOS and grub EFI binaries for UEFI.
  • Installer cannot fetch preseed — nginx root path typo; client lacks route to HTTP server during early netboot.
  • Disk not found — missing storage drivers in initrd; switch to full installer initrd or HWE kernel.

UEFI systems often need a separate DHCP filename such as ipxe.efi or grubx64.efi. Maintain parallel trees under /srv/pxe/tftp/efi/. Document which profile each rack slot uses—same rigour as tracking PHP-FPM socket paths after PHP installs on Ubuntu.

When a host boots the wrong OS version, checksum your HTTP artifacts weekly. Store SHA256 manifests beside ISOs. If a nightly sync corrupts initrd.gz, every downstream install fails identically—that is hard to debug without version pins.

End-to-End PXE PipelinePower OnF12 netbootPXE FetchDHCP + TFTPInstallPreseed applyVerifySSH + patchCMAnsibleProduction Handoff GatesSSL via Certbot — see Ubuntu SSL guideDeployer 7 user + GitLab CI runner registrationNightly DB dumps per backup playbookRegister in monitoring — disk, load, queue depth
After PXE Boot for Automated OS Installs completes, run the same hardening steps you use for live Laravel and WordPress hosts.

Security hardening on the PXE host itself

The PXE server is high trust. Restrict SSH. Allow TFTP and HTTP only from the provisioning subnet. Sign iPXE scripts when you graduate beyond lab setups. Audit late_command snippets— they run as root inside the installer context.

Segmentation beats clever crypto on a flat LAN. I have seen office DHCP pools accidentally serve production pxelinux paths. The fix was VLAN 50 for staging only, documented in runbooks beside automated server backup procedures.

Scaling beyond one site

Replicate HTTP mirrors regionally if bandwidth to Kathmandu uplinks is tight. Use rsync cron jobs from a golden mirror. For international clients—flower eCommerce stacks like Petals Agro Nepal—keep PXE assets versioned in Git with tagged releases, identical to application deploy tags.

Generate random root passwords during install if humans never log in locally. Store them in your team vault generated via a proper secret workflow; a password generator tool helps draft policy-compliant lengths before you automate vault writes.

Key Takeaways

  • PXE chains DHCP, TFTP, and HTTP to boot an unattended installer with preseed or kickstart—define once, replay on every bare-metal node.
  • Run dnsmasq and nginx on an isolated provisioning VLAN so you never fight office DHCP or production traffic.
  • Pin kernel, initrd, and preseed URLs with checksums; drift in one file breaks every parallel install simultaneously.
  • Split BIOS and UEFI boot artifacts; most “PXE broken” tickets are firmware mode mismatches, not mystery gremlins.
  • Treat post-install hardening—SSH, UFW, SSL, backups—as part of the same pipeline, not a separate weekend chore.
  • PXE complements cloud-init and golden AMI workflows; use PXE on metal, cloud metadata on VMs, one Ansible layer above both.

People Also Ask

Do I need special hardware for PXE boot?

Most server and desktop NICs ship with a PXE ROM enabled in firmware. Toggle network boot in BIOS or UEFI boot order. USB Ethernet adapters often lack PXE support—use onboard NICs for racks. Wi-Fi PXE exists but is rare in data centres; stick to wired gigabit for reliability.

Can PXE install Windows as well as Linux?

Yes. Windows Deployment Services and Microsoft Deployment Toolkit use PXE with boot.wim images. Linux-focused teams still use PXE for Ubuntu and Debian while SCCM or WDS handles Windows clients. Mixed fleets can share one DHCP server with per-MAC filenames pointing at different boot loaders.

Is PXE secure enough for production networks?

PXE alone is not encrypted; anyone on the VLAN can sniff TFTP transfers. Mitigate with isolated provisioning networks, short-lived VLANs, signed iPXE binaries, and HTTPS for stage-two payloads. Never expose the PXE HTTP mirror to the public internet without authentication.

How long does an automated PXE install take?

Ubuntu minimal installs over gigabit LAN typically finish in ten to twenty minutes depending on mirror speed, disk type, and package list. Full desktop metapackages take longer. Parallel installs scale linearly until HTTP or disk mirror throughput saturates—watch nginx access logs during batch builds.

Build repeatable infrastructure from day one

PXE Boot for Automated OS Installs turns rack provisioning from a hands-on chore into a versioned workflow you can audit and replay. Start with one dnsmasq host, one preseed file, and two test machines before you touch production. Layer PHP, Nginx, and your Deployer pipeline only after SSH and backups verify clean. If you want help designing provisioning VLANs, golden images, or the Laravel stack that sits on top, contact us or review domain and hosting services for colocated hardware planning. Related reading: Docker on Ubuntu, SSL on Ubuntu, and the home page for broader DevOps notes. Strong infrastructure starts before the first git push.

Frequently Asked Questions

PXE chains DHCP options 66 and 67, TFTP for the boot loader, and HTTP or NFS for the kernel, initrd, and preseed answer file so bare-metal machines install an OS without local media.

The NIC broadcasts a DHCP discover packet. The DHCP server assigns an IP and tells the client where to fetch boot files via options 66 and 67. The client downloads the boot loader over TFTP, executes it, loads a Linux kernel and initrd, then starts the distribution installer. A preseed or kickstart file declares locale, disk layout, packages, users, and post-install scripts so the installer never prompts and every machine lands in the same baseline state.

Install dnsmasq, nginx, syslinux-common, and pxelinux on a management VM. Create /srv/pxe/tftp for boot loaders and /srv/pxe/http for kernels, initrd, and preseed files. Copy pxelinux.0 and syslinux modules into the TFTP root. Configure dnsmasq with dhcp-boot, enable-tftp, and your provisioning subnet. Write a pxelinux menu pointing kernel and initrd URLs at nginx, with auto=true and your preseed URL on the APPEND line. Mirror Ubuntu 24.04 netboot artifacts, pin checksums, and isolate the host on a dedicated VLAN away from office DHCP.

dnsmasq, nginx, syslinux-common, and pxelinux.

Debian and Ubuntu installers consume preseed files—plain text debconf answers where order matters and late_command runs chrooted scripts for SSH keys or hardening. Red Hat family distributions use kickstart instead; you pass inst.ks=http://pxeserver/kickstart/host.cfg on the kernel line, define partitions with autopart or explicit part lines, and use %post scripts where preseed uses late_command. Same automation goal, different installer syntax.

Early directives for locale and keyboard must come first. Set partman-auto/method and choose_recipe for disk layout without prompts, pkgsel/include for baseline packages like openssh-server and ufw, and passwd fields with mkpasswd -m sha-512 hashes—not cleartext passwords in Git. preseed/late_command is where you enable UFW, inject SSH authorized keys, and register monitoring. Pin mirror URLs the same way you pin application runtime versions on production nodes.

USB suits one or two machines but is slow and inconsistent. PXE plus preseed fits on-prem racks and colo—fast, repeatable, low cost, but needs VLAN discipline and a management host. Cloud vendor images work well for AWS, GCP, and Azure VMs but carry vendor lock-in facets. Canonical MAAS suits large bare-metal fleets with inventory and IPAM but adds heavier ops overhead. Immutable Packer images suit hybrid shops. Hybrid teams often boot PXE on metal and cloud-init on VMs, then apply the same Ansible roles above both.

Work top-down: link light, DHCP log, TFTP transfer, then HTTP 200 on kernel URLs. No DHCP offer usually means a second DHCP server on the VLAN—bind dnsmasq to one interface and disable rogue router DHCP. TFTP timeouts often trace to file permissions on /srv/pxe/tftp, SELinux or AppArmor denials, or firewall blocking UDP 69. Hangs after the menu are frequently BIOS versus UEFI mismatches. Installer cannot fetch preseed when nginx root paths are wrong or the client lacks a route to the HTTP server. Checksum HTTP artifacts weekly; one corrupted initrd.gz breaks every parallel install identically.

Most server and desktop NICs ship with a PXE ROM enabled in firmware. Toggle network boot in BIOS or UEFI boot order and use onboard NICs for racks—USB Ethernet adapters often lack PXE support.

PXE alone is not encrypted; anyone on the VLAN can sniff TFTP transfers. Mitigate with isolated provisioning networks, short-lived VLANs, signed iPXE binaries, and HTTPS for stage-two payloads after iPXE chains in. Restrict TFTP and HTTP on the PXE host to the provisioning subnet only. Never expose the HTTP mirror to the public internet without authentication. Audit late_command snippets—they run as root inside the installer. Segmentation beats clever crypto on a flat LAN.

Ubuntu minimal installs over gigabit LAN typically finish in ten to twenty minutes depending on mirror speed, disk type, and package list.

Yes. Windows Deployment Services and Microsoft Deployment Toolkit use PXE with boot.wim images. Linux-focused teams still use PXE for Ubuntu and Debian while SCCM or WDS handles Windows clients. Mixed fleets can share one DHCP server with per-MAC filenames pointing at different boot loaders.

Running dnsmasq on the same broadcast domain as office Wi-Fi or production stacks risks DHCP scope collisions that blackhole laptops, printers, and servers. A dedicated provisioning VLAN keeps PXE DHCP scopes away from production traffic. I have seen office DHCP pools accidentally serve production pxelinux paths—the fix was VLAN 50 for staging only, documented in runbooks. Restrict PXE host SSH and allow TFTP and HTTP only from the provisioning subnet.

dnsmasq combines DHCP and TFTP in one daemon with a small config surface. It assigns IPv4 leases, sets dhcp-boot to pxelinux.0 with next-server and filename via options 66 and 67, and serves the TFTP root at /srv/pxe/tftp. Bind it only to your provisioning interface; never run two DHCP servers on the same broadcast domain. Restart with systemctl and watch journalctl -u dnsmasq -f during test boots to confirm clients receive offers and filenames.

Maintain parallel boot artifact trees. Use pxelinux and syslinux modules under /srv/pxe/tftp/ for legacy BIOS. UEFI systems often need a separate DHCP filename such as ipxe.efi or grubx64.efi with EFI binaries under /srv/pxe/tftp/efi/. Most PXE broken tickets are firmware mode mismatches, not mystery gremlins—document which profile each rack slot uses with the same rigour as tracking PHP-FPM socket paths after version upgrades on application servers.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: