elfshoe - Reference¶
Command-Line Tools¶
elfshoe¶
The elfshoe command generates iPXE boot menu scripts from YAML configuration files.
Command Line Usage¶
# Generate menu with validation (recommended)
elfshoe
# Fast generation (no validation)
elfshoe --skip-validation
# Custom config and output files
elfshoe -c custom-config.yaml -o custom-elfshoe.ipxe
# Quiet mode (no output unless errors)
elfshoe --quiet
# Show help
elfshoe --help
Command Options¶
-c, --config FILE- Path to config file (default:config.yaml)-o, --output FILE- Output file path (default:elfshoe.ipxe)--skip-validation- Skip URL validation for faster generation--quiet- Quiet mode, only show errors--help- Show help message
Command Line Options¶
elfshoe [OPTIONS]
Options:
-c, --config FILE Configuration file (default: config.yaml)
-o, --output FILE Output file (default: elfshoe.ipxe)
--no-validate Skip URL validation (faster)
--quiet Minimal output
--help Show help message
ipxelint¶
The ipxelint tool validates iPXE scripts for syntax errors and common mistakes.
Basic Usage¶
# Validate a single file
ipxelint elfshoe.ipxe
# Validate multiple files
ipxelint *.ipxe
# Treat warnings as errors (CI-friendly)
ipxelint --strict elfshoe.ipxe
# Only show errors
ipxelint --quiet elfshoe.ipxe
What It Checks¶
- Shebang: Ensures script starts with
#!ipxe - Menu balance: Warns if menu/choose statements are unbalanced
- Label references: Detects undefined label references in goto statements
- Command syntax: Warns about unknown or potentially misspelled commands
Exit Codes¶
0: All files passed validation1: At least one file had errors (or warnings with--strict)
Example Output¶
✓ elfshoe.ipxe: OK
⚠️ custom.ipxe: WARNINGS
Line 12: Unknown or potentially misspelled command: 'slepe'
❌ broken.ipxe: FAILED
Line 1: Missing or invalid #!ipxe shebang
Line 15: Reference to undefined label: 'non_existent'
Command Line Options Full Reference¶
-c, --config FILE # Config file (default: config.yaml)
-o, --output FILE # Output file (default: elfshoe.ipxe)
--no-validate # Skip URL validation (faster)
-q, --quiet # Minimal output
--version # Show version
-h, --help # Show help
Configuration File Structure¶
menu:
title: "Your Menu Title"
default_item: "distribution_menu"
timeout: 30000 # Menu timeout (ms)
error_timeout: 30000 # Error display timeout (ms)
distributions:
distro_name:
enabled: true|false
label: "Display Label"
type: "static"|"dynamic"
# Architecture support (optional)
arch_map:
arm64: aarch64 # Map iPXE arch names to distro arch names
x86_64: x86_64
# For static type:
versions:
- version: "X"
name: "Release Name" # Optional
architectures: [x86_64, arm64] # Optional: per-version control
# For dynamic type:
metadata_provider: "provider_name" # e.g., "fedora"
metadata_url: "https://..."
metadata_filter:
variant: "Server"
architectures: [x86_64, aarch64] # Filter for specific architectures
latest: 3 # Optional: limit to N latest versions
# Common fields:
url_template: "http://example.com/{version}/{arch}/path" # Use {arch} placeholder
boot_files:
kernel: "path/to/vmlinuz"
initrd: "path/to/initrd.img"
boot_params: "kernel_params_here"
additional_items:
- id: "unique_id"
label: "Display Label"
type: "chain"|"shell"|"exit"
url: "http://..." # for chain type only
URL Templates¶
Use {version} and {arch} placeholders in URL templates:
# Fedora with architecture support
url_template: "http://download.fedoraproject.org/pub/fedora/linux/releases/{version}/Server/{arch}/os"
# CentOS Stream with architecture
url_template: "http://mirror.stream.centos.org/{version}-stream/BaseOS/{arch}/os"
# Debian with architecture
url_template: "http://deb.debian.org/debian/dists/{version}/main/installer-{arch}/current/images/netboot/debian-installer/{arch}"
Architecture Support¶
Overview¶
elfshoe supports multiple CPU architectures with automatic client filtering:
- x86_64 - 64-bit x86 (most servers and desktops)
- arm64 - 64-bit ARM (Raspberry Pi 4, Apple Silicon, AWS Graviton)
- i386 - 32-bit x86 (legacy systems)
- arm - 32-bit ARM (older embedded devices)
Architecture Name Mapping¶
Different distributions use different architecture names. Use arch_map to translate:
distributions:
fedora:
arch_map:
arm64: aarch64 # iPXE calls it arm64, Fedora calls it aarch64
x86_64: x86_64
debian:
arch_map:
x86_64: amd64 # iPXE calls it x86_64, Debian calls it amd64
arm64: arm64
Common mappings:
| iPXE Name | Fedora/RHEL | Debian/Ubuntu |
|---|---|---|
| x86_64 | x86_64 | amd64 |
| arm64 | aarch64 | arm64 |
| i386 | i386 | i386 |
| arm | armhfp | armhf |
Dynamic Distributions (Metadata-Driven)¶
For Fedora and other distributions with metadata providers:
fedora:
type: dynamic
metadata_filter:
variant: Server
architectures: [x86_64, aarch64] # ← Filter metadata
latest: 3
arch_map:
arm64: aarch64
url_template: "https://.../{version}/Server/{arch}/os"
Behavior:
- Fetches metadata for specified architectures
- Only includes versions that exist in metadata
- Validates URLs for each architecture
- Skips architectures not available in metadata
Static Distributions (Manual Configuration)¶
For distributions without metadata providers:
debian:
type: static
arch_map:
x86_64: amd64
versions:
- version: "bookworm"
name: "12 Bookworm"
architectures: [x86_64, arm64] # ← Per-version control
- version: "bullseye"
name: "11 Bullseye"
architectures: [x86_64] # Only x86_64 for this version
Behavior:
- You specify which architectures each version supports
- Can vary architectures per version
- Validates URLs for each specified architecture
Client-Side Filtering¶
Generated menus use iseq ${buildarch} to filter items:
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) ||
Result:
- x86_64 clients only see x86_64 menu items
- ARM64 clients only see ARM64 menu items
- No manual selection needed
- No wrong architecture served
Single Architecture (Default)¶
If you don't specify architectures, defaults to x86_64 only:
centos:
type: static
versions:
- version: "9"
url_template: "http://mirror.centos.org/{version}/BaseOS/x86_64/os"
This is backward compatible with existing configurations.
Boot Parameters¶
Use {base_url} in boot parameters:
# Repository installation
boot_params: "inst.repo={base_url}/"
# Network configuration
boot_params: "ip=dhcp inst.repo={base_url}/"
# Text mode
boot_params: "inst.text inst.repo={base_url}/"
Command-Line Options¶
-c, --config FILE # Config file (default: config.yaml)
-o, --output FILE # Output file (default: elfshoe.ipxe)
--no-validate # Skip URL validation (faster)
-q, --quiet # Minimal output
--version # Show version
-h, --help # Show help
File Locations¶
Project Root/
├── config.yaml # Main configuration (see docs/examples/config.yaml)
├── elfshoe.ipxe # Generated menu (output)
├── docs/
│ └── examples/
│ ├── config.yaml # Complete example with all features
│ └── 99-dnsmasq-pxe-ipxe.conf # dnsmasq config example
├── src/elfshoe/ # Package source
│ ├── core/ # Core components
│ ├── distributions/ # Distribution plugins
│ └── templates/ # Jinja2 templates
└── tests/ # Test suite
Adding a Distribution¶
Static (Simple)¶
Add to config.yaml:
distributions:
mylinux:
enabled: true
type: "static"
label: "My Linux"
versions:
- version: "1.0"
label: "My Linux 1.0"
url_template: "http://mirror.example.com/{version}/os"
boot_files:
kernel: "vmlinuz"
initrd: "initrd.img"
boot_params: ""
Dynamic Distribution (Automatic Version Detection)¶
For distributions like Fedora that support automatic version detection:
distributions:
fedora:
enabled: true
type: "dynamic"
label: "Fedora"
metadata_provider: "fedora"
metadata_url: "https://fedoraproject.org/releases.json"
metadata_filter:
variant: "Server"
architectures: [x86_64, aarch64]
latest: 3 # Only show 3 most recent versions
arch_map:
arm64: aarch64 # Map iPXE arm64 to Fedora aarch64
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}/"
Note: To add custom metadata providers, see the Adding Distributions guide.
Troubleshooting¶
Menu Generation is Slow¶
# Skip URL validation for faster generation (development mode)
elfshoe --skip-validation
# or
elfshoe --no-validate
Tip: Use validation in production to catch broken URLs, but skip it during development/testing.
Menu Generation Fails¶
# Run with validation to see which URLs are failing
elfshoe
# Test specific URL manually
curl -I http://your-mirror-url/vmlinuz
Boot Files Not Found (404 errors)¶
- Check that the
url_templateis correct for your mirror - Verify
boot_filespaths match your distribution's file structure - Test the full URL:
{url_template}/{kernel_path} - Try a different mirror if the current one is down
iPXE Shows "No Such File"¶
This usually means:
- The URL in the generated menu is incorrect
- The web server hosting the files is not accessible from the client
- The file paths in
boot_filesdon't match the actual file locations
Solutions:
# Regenerate menu with validation to check URLs
elfshoe
# Verify your web server can serve the files
curl http://your-server/path/to/vmlinuz
# Check the generated elfshoe.ipxe file for correct URLs
cat elfshoe.ipxe | grep -A5 "boot_fedora"
Performance¶
- With validation: 30-45 seconds (checks all URLs exist)
- Without validation: <1 second (generates menu only)
- Recommendation: Use validation before deploying to production
Version Detection¶
Fedora (Dynamic)¶
- Fetches versions from:
https://fedoraproject.org/releases.json - Filters by:
variant=Server,arch=x86_64 - Returns: Latest 3-5 supported versions automatically
Other Distributions¶
- CentOS, Debian, Rocky: Use static version lists
- Custom distributions: Can add dynamic metadata providers (see contributor docs)
iPXE Boot Process¶
How It Works¶
- Client machine boots via PXE
- DHCP server provides iPXE binary location
- iPXE loads and fetches
elfshoe.ipxefrom your web server - User selects OS from menu
- iPXE downloads kernel and initrd
- Boot proceeds with specified parameters
Generated Menu Structure¶
#!ipxe
:start
menu Network Boot Menu
item fedora_38 Fedora 38 Server
choose selected
goto ${selected}
:fedora_38
echo Booting Fedora 38 Server...
initrd http://mirror/fedora/38/images/pxeboot/initrd.img || goto error
kernel http://mirror/fedora/38/images/pxeboot/vmlinuz initrd=initrd.img inst.repo=http://mirror/fedora/38/ || goto error
boot
:error
echo Boot failed!
prompt --timeout ${error_timeout}
goto start
Boot Parameters¶
Common parameters you can add to boot_params:
- Fedora/RHEL:
inst.repo={base_url}/ inst.ks=http://server/kickstart.cfg - Debian/Ubuntu:
auto=true url=http://server/preseed.cfg - Generic:
console=ttyS0,115200(for serial console)
Supported File Types¶
- Kernel:
vmlinuz,linux,bzImage - Initrd:
initrd.img,initrd.gz,initramfs
Related Documentation¶
- Home - Full documentation
- Getting Started - Concepts and overview
- Contributing - For contributors