elfshoe - Getting Started¶
This guide walks you through creating your first iPXE boot menu with elfshoe.
Prerequisites¶
Before using elfshoe, you need:
- Server infrastructure - DHCP, TFTP, and HTTP servers configured for network booting
- See the Server Setup Guide for complete instructions
-
Includes getting iPXE boot files, configuring DHCP/TFTP, and setting up HTTP delivery
-
Python 3.10 or higher - For running elfshoe (it probably works on earlier but is untested)
- Network boot enabled - On client machines (BIOS/UEFI settings)
New to network booting? Start with the Server Setup Guide to get your infrastructure ready.
How It Works¶
- Configure - Define OS distributions in
config.yaml - Generate - Run
elfshoeto createelfshoe.ipxe - Deploy - Serve
elfshoe.ipxefrom your web server - Boot - Client machines PXE boot and display your menu
Quick Example¶
1. Create config.yaml¶
Start with the example configuration:
# Copy the example config
cp docs/examples/config.yaml config.yaml
# Or view it at: docs/examples/config.yaml
Example configuration:
# iPXE Menu Generator Configuration
# Complete example showing all features
# Main menu settings
menu:
title: "Network Boot Menu"
default_item: "fedora_menu"
timeout: 30000 # milliseconds (30 seconds)
error_timeout: 30000 # milliseconds - how long to show errors before returning to menu
# Distribution configurations
# Each distribution can be either "dynamic" (auto-fetch versions) or "static" (manual versions)
distributions:
# Example 1: Dynamic distribution with metadata provider
# Fedora versions are fetched automatically from releases.json
fedora:
enabled: true
label: "Fedora"
type: "dynamic"
metadata_provider: "fedora" # Use Fedora metadata fetcher
metadata_url: "https://fedoraproject.org/releases.json"
# Metadata filters control which versions/architectures to include
metadata_filter:
variant: "Server" # Only Server variant (other options: Workstation, Cloud, etc.)
architectures: [x86_64, aarch64] # Fetch these architectures from metadata
latest: 3 # Only show 3 most recent versions
# Architecture name mapping: iPXE uses different names than distributions
arch_map:
arm64: aarch64 # Map iPXE "arm64" to Fedora's "aarch64"
x86_64: x86_64 # iPXE and Fedora both use "x86_64"
# URL template with {version} and {arch} placeholders
url_template: "http://download.fedoraproject.org/pub/fedora/linux/releases/{version}/Server/{arch}/os"
boot_files:
kernel: "images/pxeboot/vmlinuz"
initrd: "images/pxeboot/initrd.img"
boot_params: "inst.repo={base_url}/"
# Example 2: Static distribution without architecture mapping
# CentOS versions are specified manually
centos:
enabled: true
label: "CentOS Stream"
type: "static"
# Manually specify versions and their supported architectures
versions:
- version: "10"
architectures: [x86_64] # Stream 10 only supports x86_64 currently
- version: "9"
architectures: [x86_64, arm64] # Stream 9 supports both
url_template: "http://mirror.stream.centos.org/{version}-stream/BaseOS/{arch}/os"
boot_files:
kernel: "images/pxeboot/vmlinuz"
initrd: "images/pxeboot/initrd.img"
boot_params: "inst.repo={base_url}/"
# Example 3: Static distribution with arch_map and release names
# Debian uses different architecture names than iPXE
debian:
enabled: true
label: "Debian"
type: "static"
# Debian calls x86_64 "amd64" - use arch_map to translate
arch_map:
x86_64: amd64 # iPXE "x86_64" → Debian "amd64"
arm64: arm64 # Both use "arm64"
versions:
- version: "bookworm"
name: "12 Bookworm" # Optional: human-friendly release name
architectures: [x86_64, arm64]
- version: "trixie"
name: "13 Trixie"
architectures: [x86_64, arm64]
url_template: "http://deb.debian.org/debian/dists/{version}/main/installer-{arch}/current/images/netboot/debian-installer/{arch}"
boot_files:
kernel: "linux"
initrd: "initrd.gz"
boot_params: ""
# Additional menu items (non-distribution options)
additional_items:
# Chain to another iPXE script
- id: "netboot"
label: "netboot.xyz"
type: "chain"
url: "http://boot.netboot.xyz"
# Open iPXE shell
- id: "shell"
label: "iPXE Shell"
type: "shell"
# Exit to BIOS/UEFI
- id: "exit"
label: "Exit to BIOS"
type: "exit"
2. Generate menu¶
3. Result¶
You get a elfshoe.ipxe file that looks like:
#!ipxe
dhcp
:start
menu Network Boot Menu
item --gap -- Operating Systems:
item fedora_menu Fedora
item centos_menu CentOS Stream
item debian_menu Debian
item --gap -- Other Options:
item netboot netboot.xyz
item --gap -- Advanced:
item shell iPXE Shell
item exit Exit to BIOS
choose --default fedora_menu --timeout 30000 target && goto ${target}
:fedora_menu
# Architecture-aware menu - shows only matching client architecture
menu Fedora - Select Version
iseq ${buildarch} x86_64 && item fedora_43_x86_64 Fedora 43 Server (x86_64) ||
iseq ${buildarch} arm64 && item fedora_43_arm64 Fedora 43 Server (aarch64) ||
iseq ${buildarch} x86_64 && item fedora_42_x86_64 Fedora 42 Server (x86_64) ||
iseq ${buildarch} arm64 && item fedora_42_arm64 Fedora 42 Server (aarch64) ||
item --gap --
item back_fedora_menu Back to main menu
choose --default fedora_43_x86_64 target && goto ${target}
:fedora_43_x86_64
initrd http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/x86_64/os/images/pxeboot/initrd.img
chain http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/x86_64/os/images/pxeboot/vmlinuz initrd=initrd.img inst.repo=http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/x86_64/os/ || goto fedora_menu_error
:fedora_43_arm64
initrd http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/aarch64/os/images/pxeboot/initrd.img
chain http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/aarch64/os/images/pxeboot/vmlinuz initrd=initrd.img inst.repo=http://download.fedoraproject.org/pub/fedora/linux/releases/43/Server/aarch64/os/ || goto fedora_menu_error
# ... similar sections for other versions ...
Key features:
- Architecture-aware menus - x86_64 clients only see x86_64 options, ARM64 clients only see ARM64 options
- Automatic filtering - Uses iPXE's
iseq ${buildarch}to show only compatible entries - Human-friendly labels - "Fedora 43 Server (x86_64)" clearly shows what you're booting
- Error handling - Built-in navigation and error recovery
Key Concepts¶
Architecture Support¶
elfshoe automatically handles multiple CPU architectures (x86_64, ARM64, etc.) with smart client filtering:
What you configure:
distributions:
fedora:
type: dynamic
metadata_filter:
variant: Server
architectures: [x86_64, aarch64] # Fetch both architectures
arch_map:
arm64: aarch64 # Map iPXE's arm64 to Fedora's aarch64
What clients see:
x86_64 client menu:
Fedora - Select Version
• Fedora 43 Server (x86_64)
• Fedora 42 Server (x86_64)
• Fedora 41 Server (x86_64)
ARM64 client menu:
Fedora - Select Version
• Fedora 43 Server (aarch64)
• Fedora 42 Server (aarch64)
• Fedora 41 Server (aarch64)
How it works:
- Uses iPXE's
${buildarch}variable to detect client architecture iseq ${buildarch} x86_64 && item ...shows items only to matching clients- No wrong architecture served - clients only see what works for them
Supported architectures:
x86_64- 64-bit x86 (most common)arm64- 64-bit ARM (Raspberry Pi 4, Apple Silicon, etc.)i386- 32-bit x86 (legacy)arm- 32-bit ARM (older devices)
Static vs Dynamic Distributions¶
Static - You specify versions and architectures manually:
distributions:
debian:
type: "static"
arch_map:
x86_64: amd64 # Map iPXE names to Debian names
versions:
- version: "bookworm"
name: "12 Bookworm"
architectures: [x86_64, arm64]
Dynamic - Versions and architectures fetched automatically from metadata:
distributions:
fedora:
type: "dynamic"
metadata_provider: "fedora"
metadata_url: "https://fedoraproject.org/releases.json"
metadata_filter:
variant: Server
architectures: [x86_64, aarch64]
URL Validation¶
By default, the generator checks that kernel/initrd files exist before adding them to the menu:
- Fast mode (
elfshoe --no-validate): Skip validation (~1 second) - Validated mode (
elfshoe): Check all URLs (~30-45 seconds)
Use fast mode during development, validated mode before deployment.
Note: With multi-architecture support, each architecture is validated separately, so validation may take longer for distributions with multiple architectures.
Architecture Overview¶
For detailed architecture, see Architecture Documentation.
Common Workflows¶
Adding a New Distribution¶
Option 1: Static (simple)
distributions:
rocky:
enabled: true
type: "static"
label: "Rocky Linux"
arch_map:
arm64: aarch64 # Map architecture names if needed
versions:
- version: "9"
label: "Rocky Linux 9"
architectures: [x86_64, arm64] # Optional: specify per version
url_template: "http://mirror.example.com/rocky/{version}/BaseOS/{arch}/os"
boot_files:
kernel: "images/pxeboot/vmlinuz"
initrd: "images/pxeboot/initrd.img"
Option 2: Dynamic (advanced)
See Adding Distributions for creating metadata fetcher plugins.
Customizing Boot Parameters¶
Testing Your Menu¶
# Quick test without validation
elfshoe --skip-validation
# Check generated menu
cat elfshoe.ipxe
# Validate all URLs work
elfshoe
Performance¶
- Without validation: <1 second
- With validation: 30-45 seconds (depends on network/mirrors)
- URL checks: Parallel HEAD requests with 10s timeout
Security¶
- No code execution - Config is pure YAML data, no code
- Safe YAML parsing - Uses
yaml.safe_load()only - URL validation - Prevents broken links in menus
- Timeouts - All HTTP requests have 10 second timeouts
Next Steps¶
Deploy Your Menu¶
Copy the generated elfshoe.ipxe to your HTTP server:
# Example: Copy to nginx web root
sudo cp elfshoe.ipxe /var/www/pxe/
# Or to Apache
sudo cp elfshoe.ipxe /var/www/html/pxe/
Don't have a server set up yet? See the Server Setup Guide for:
- Installing and configuring DHCP/TFTP servers (dnsmasq, ISC DHCP, Windows)
- Setting up HTTP servers (nginx, Apache)
- Getting iPXE boot files
- Complete deployment instructions
Test Network Booting¶
- Enable network boot in your client's BIOS/UEFI settings
- Boot the client - it should:
- Get an IP from DHCP
- Download iPXE bootloader via TFTP
- Load your elfshoe menu via HTTP
- Display your boot options
Troubleshooting¶
Menu doesn't appear:
- Verify HTTP server is accessible:
curl http://your-server/elfshoe.ipxe - Check client can reach server (ping, firewall rules)
- Review DHCP/TFTP logs
URLs fail validation:
- Check mirror URLs are accessible
- Try a different mirror
- Use
--skip-validationfor testing (not recommended for production)
For infrastructure issues, see the Server Setup Guide - Troubleshooting.
Learn More¶
- Reference - Complete command and configuration reference
- Server Setup - DHCP, TFTP, HTTP configuration details
- Adding Distributions - Extend with new OSes
- Contributing - Add features or fix bugs