PXE Boot

This guide describes how to network boot Oxide instances using PXE (Preboot eXecution Environment), netboot.xyz, and a custom iPXE disk image. PXE boot does not require local storage, which is valuable for testing, debugging, recovery scenarios, and organizations with existing PXE workflows.

Prerequisites

To follow this guide you’ll need the following.

  • An Oxide instance to host the netboot.xyz server running Ubuntu 24.04.

  • Administrative access to configure the netboot.xyz server.

  • Network connectivity between the netboot.xyz server and PXE boot instances.

  • Basic familiarity with the Linux command line.

Configure the netboot.xyz Server

We’ll configure the netboot.xyz server directly from the Oxide instance it will run on using Ansible playbooks.

Note
The netboot.xyz server can use either HTTP or HTTPS. For simplicity, this guide uses HTTP. For production deployments, HTTPS is recommended.

Install netboot.xyz

  1. Clone the netboot.xyz repository.

    sudo git clone https://github.com/netbootxyz/netboot.xyz.git /opt/netboot.xyz
  2. Install required packages.

    sudo apt-get update
    sudo apt-get install -y software-properties-common
    sudo add-apt-repository --yes --update ppa:ansible/ansible
    sudo apt-get install -y ansible git apache2 mtools build-essential liblzma-dev jq
  3. (Optional) Configure the site name and boot domain within /opt/netboot.xyz/user_overrides.yml.

    site_name: example.com
    boot_domain: boot.example.com
  4. Run the Ansible playbook.

    cd /opt/netboot.xyz
    sudo ansible-playbook -i inventory/hosts site.yml
Note
This step will take some time, which is dependent on your server configuration and available resources.
  1. Verify the installation by navigating to http://${INSTANCE_IP} in a web browser.

(Optional) Configure HTTPS

If this is a production deployment, consider enabling HTTPS.

  1. Obtain a TLS certificate for your server. Refer to Creating TLS Certificates for more information.

  2. Configure Apache to use HTTPS on port 443.

  3. Update your iPXE scripts to use HTTPS URLs.

Warning
If using HTTPS, ensure your iPXE binary is built with HTTPS support enabled.

Create the iPXE Boot Image

Install Dependencies

To create a UEFI-compatible iPXE image for Oxide.

  1. Install build dependencies.

    sudo apt-get update
    sudo apt-get install -y software-properties-common
    sudo apt-get install -y git mtools build-essential liblzma-dev
Note
You only need to do this if you did not install them in the previous section when setting up the netboot.xyz server (for example, if you are building the iPXE image on a different machine).
  1. Clone the iPXE repository.

    cd ~
    git clone https://github.com/ipxe/ipxe.git
    cd ipxe
Note
There is a known issue documented in this discussion on github regarding warnings when building iPXE. If you are on versions of the build tooling that results in this warning, you can either revert to commit 6ca597e via git checkout 6ca597e or remove the -Werror flag to prevent the compilation from failing on warnings.

Create the Embedded iPXE Script

  1. Create a file named embed.ipxe with the boot logic. Replace ${INSTANCE_IP} with the IP address of your Oxide instance running the netboot.xyz server.

    cat > ~/ipxe/src/embed.ipxe << EOF

    #!ipxe

    echo "===> Embedded iPXE script running"
    sleep 2

    dhcp
    isset ${ip} || goto no_ip

    echo "===> Got IP: ${ip} via ${net0/mac}"
    echo "===> Attempting to chain to http://${INSTANCE_IP}/menu.ipxe"
    sleep 2

    chain http://${INSTANCE_IP}/menu.ipxe || goto fail
    exit

    :no_ip
    echo "===> No IP address acquired"
    shell

    :fail
    echo "===> Failed to chain to netboot.xyz"
    shell

    EOF
Note
If you are booting on the same VPC with the netboot.xyz server, you will use the internal IP address. If you are outside the VPC, you will need to use the floating or ephemeral IP address.

Build the iPXE Binary

  1. Compile the UEFI-compatible iPXE binary.

    cd ~/ipxe/src
    make bin-x86_64-efi/ipxe.efi EMBED=embed.ipxe
  2. Create the bootable disk image.

    cd ~/ipxe/src

    # Create directory structure for EFI boot.
    mkdir -p bootimg/EFI/BOOT

    # Copy iPXE binary to correct EFI location.
    cp bin-x86_64-efi/ipxe.efi bootimg/EFI/BOOT/BOOTX64.EFI

    # Create FAT-formatted disk image.
    mkfs.vfat -C ipxe.img 65536

    # Copy boot files into the image.
    mcopy -i ipxe.img -s bootimg/* ::
  3. Verify that an ipxe.img file was successfully created.

    ls ipxe.img

Deploy to Oxide

This example uses the Oxide CLI. Refer to Getting Started with the Oxide CLI for installation and configuration instructions. Alternatively, you can use the Oxide API or web console.

Upload the iPXE Image

Upload the ipxe.img iPXE image to Oxide using the CLI. You will need to replace ${PROJECT} with the name of your Oxide project.

oxide disk import \
--project ${PROJECT} \
--path ipxe.img \
--disk ipxe-boot \
--description "iPXE boot image." \
--snapshot ipxe-boot \
--image ipxe \
--image-description "iPXE boot image." \
--image-os "Netboot.xyz" \
--image-version "v1.2.3" \
--disk-block-size 512

Retrieve the Image ID

oxide image view --image ipxe | jq .id

PXE Boot an Instance

  1. Create an instance configuration file (e.g., instance.json) with the boot disk configuration:

    cat > instance.json << EOF
    {
    "name": "pxe-test-instance",
    "description": "PXE boot test instance",
    "boot_disk": {
    "type": "create",
    "name": "pxe-test-boot",
    "size": 8589934592,
    "description": "iPXE boot disk",
    "disk_source": {
    "type": "image",
    "image_id": "${IMAGE_ID}"
    }
    },
    "hostname": "pxe-test",
    "ncpus": 2,
    "memory": 4294967296,
    "network_interfaces": {
    "type": "default"
    }
    }

    EOF

    Replace ${IMAGE_ID} with the image ID from the previous step.

  2. Create the instance using the JSON configuration:

    oxide instance create \
    --project ${OXIDE_PROJECT} \
    --json-body instance.json

    The instance will start automatically by default.

  3. Connect to the instance serial console to monitor the boot process:

    oxide instance serial console \
    --project ${OXIDE_PROJECT} \
    --instance pxe-test-instance
Note
You can also view the serial console using the Oxide web console. Refer to Instance Management for details.

Boot Menu Options

When the instance boots, you should see the following boot menu options.

  1. iPXE initialization: The embedded script runs and attempts DHCP

  2. Network configuration: An IP address is acquired

  3. Chainloading: The script connects to your netboot.xyz server

  4. Menu display: The netboot.xyz boot menu appears

The netboot.xyz menu provides options for:

  • Operating System Installers: Various Linux distributions, Windows PE, etc.

  • Live Environments: Diagnostic and recovery tools

  • Utilities: System maintenance and testing tools

  • Custom Options: Your own additions to the menu

Note
Oxide provides you with a serial connection to the console, so any boot images that require a graphical display will hang at the boot process trying to access a graphics device (such as VNC). Most Linux distros will work if you pass console=tty0 console=ttyS0,115200n8 to the kernel at boot time. For test purposes, the alpine distribution image is known to work without modification.

Customize the Boot Menu

You can customize the netboot.xyz menu by modifying /var/www/html/netboot.xyz/menu.ipxe on your server. For example, to create a hybrid menu that offers both local and official netboot.xyz options:

#!ipxe

# Disable signature verification for chaining.
set sigs_enabled false

:start
menu iPXE Boot Options
item local Boot from local netboot.xyz
item official Chain to official netboot.xyz
item shell Drop to iPXE shell
choose option || goto start
goto ${option}

:local
chain http://${INSTANCE_IP}/menu.ipxe

:official
chain https://boot.netboot.xyz

:shell
shell

Troubleshooting

Common Issues and Solutions

Instance doesn’t boot from iPXE image

  • Verify the disk image is properly formatted and contains the EFI boot files

  • Check that the instance is configured to boot from the correct disk

DHCP fails to acquire IP address

  • Confirm network connectivity between the instance and DHCP server

  • Check VPC firewall rules allow DHCP traffic (ports 67/68)

  • Verify the instance’s network interface is properly configured

Cannot reach netboot.xyz server

  • Test HTTP connectivity from another system on the same network

  • Confirm the server hostname/IP is correct in the iPXE script

  • Check firewall rules allow HTTP/HTTPS traffic to the server

Menu doesn’t load or appears corrupted

  • Verify the netboot.xyz server is properly installed and configured

  • Check Apache error logs: sudo tail -f /var/log/apache2/error.log

  • Test the menu URL directly in a web browser

HTTPS certificate errors

  • Ensure your iPXE binary was compiled with HTTPS support

  • Verify the server certificate is valid and properly configured

  • Consider using HTTP for testing, then migrate to HTTPS

Advanced Troubleshooting

For deeper debugging, you can:

  1. Enable iPXE debugging by modifying the embedded script to include diagnostic commands

  2. Access the iPXE shell by selecting the shell option or handling script failures

  3. Monitor network traffic using packet capture tools on the server

  4. Review server logs for Apache access and error information

Related Resources

API Reference

ActionDescriptionLink

Import Disk

Upload a disk image to an Oxide project for use as instance storage.

disk_import

Create Instance

Create a new virtual machine instance with specified configuration.

instance_create

Start Instance

Power on a virtual machine instance.

instance_start

Serial Console

Access the serial console of a running instance for monitoring and debugging.

instance_serial_console