mirror of
https://github.com/netbootxyz/netboot.xyz.git
synced 2026-07-18 00:45:23 +00:00
7.4 KiB
7.4 KiB
AGENTS.md
Guidelines for AI coding agents working in the netboot.xyz repository.
Project Summary
netboot.xyz generates iPXE bootloaders and menus for 190+ operating systems using Ansible and Jinja2 templates. There is no application code in a traditional sense — the project produces .ipxe scripts and bootloader binaries.
Build Commands
# Syntax check (fast, run first)
ansible-playbook site.yml --syntax-check
# Lint Ansible tasks
ansible-lint -v roles/netbootxyz/tasks
# Full local build (generates menus + bootloaders to /var/www/html)
ansible-playbook site.yml
# Menu-only build (skip bootloader compilation)
ansible-playbook site.yml -e "generate_disks=false generate_checksums=false generate_signatures=false"
# Docker build (outputs to buildout/)
docker build -t localbuild --platform=linux/amd64 -f Dockerfile .
docker run --rm -it --platform=linux/amd64 -v $(pwd):/buildout localbuild
# Release builds
./script/build_release dev # Development
./script/build_release pr # Pull request test
./script/build_release rc # Release candidate
./script/build_release release # Production
./script/build_release rolling # Rolling
CI Checks (what PRs must pass)
ansible-playbook site.yml --syntax-checkansible-lint -v roles/netbootxyz/tasks- Full Docker build via
./script/build_release pr
Testing
Molecule tests exist but require Docker:
pip install molecule molecule-docker
molecule test
There are no unit tests. Validation is done through syntax checks, linting, and full builds.
Code Style
YAML / Ansible
- Start every YAML file with
---on line 1. - Use 2-space indentation consistently.
- Use fully-qualified collection names (FQCN) for all modules:
ansible.builtin.template,ansible.builtin.set_fact,ansible.builtin.shell, etc.- Never use short names like
template:orshell:.
- Use
snake_casefor all variable names:boot_domain,generate_menus,netbootxyz_root. - Guard booleans with the
| default(true) | boolpattern:when: - generate_menus | default(true) | bool - Use
when:as a list even for single conditions. - Use descriptive
name:for every task. - The
.ansible-lintconfig skips these rules (do not add workarounds for them):command-instead-of-module,command-instead-of-shellno-changed-when,risky-shell-pipeliteral-compare,var-naming[no-role-prefix]
iPXE Templates (.ipxe.j2 files)
- Start with
#!ipxeshebang on line 1. - Add a comment header with OS name and URL on lines 2-4.
- iPXE scripts are flat — do not indent iPXE commands.
- Use
#for comments inside templates. - Variable conventions:
- iPXE runtime variables:
${variable_name}(evaluated at boot time) - Jinja2 template variables:
{{ variable }}(evaluated at build time) - These are often mixed:
${live_endpoint}{{ endpoints.foo.path }}
- iPXE runtime variables:
- Labels use
:label_nameinsnake_case. - Navigation pattern:
goto ${menu} ||at template start. - User selection:
choose <var> || goto <exit_label>. - Exit pattern: clear menu and
exit 0::distro_exit clear menu exit 0 - Error pattern: echo, prompt, return to menu:
:error echo Error occurred, press any key to return to menu prompt goto main_menu - Fallback chains:
command || goto fallbackfor graceful degradation. - Architecture mapping varies by OS family:
- Red Hat:
x86_64→x86_64,arm64→aarch64 - Debian:
x86_64→amd64,arm64→arm64
- Red Hat:
- Guard optional values:
isset ${variable}in iPXE,{% if value.field is defined %}in Jinja2.
Jinja2 Patterns
- Loop over releases:
{% for item in releases.<distro>.versions %} - Sort by name:
{% for key, value in releases.items() | sort(attribute='1.name') %} - Filter enabled items:
{% if value.enabled is defined and value.enabled | bool %} - Template iteration uses
with_community.general.filetreein tasks.
OS Definition Schema (defaults/main.yml)
releases:
distro_key: # lowercase, no hyphens (e.g., almalinux, rockylinux)
name: "Display Name"
mirror: "http://mirror.url"
base_dir: "path/on/mirror"
enabled: true
menu: linux # one of: linux, bsd, dos, unix
versions:
- code_name: "version_id"
name: "Display Version"
Optional fields: archive_mirror, paths, flavors, platforms, version.
Utility Definition Schema (defaults/main.yml)
utilitiesefi: # or utilitiespcbios64, utilitiespcbios32, utilitiesarm
utility_key:
name: "Display Name"
enabled: true
type: direct # one of: direct, ipxemenu, memdisk, memtest, sanboot
kernel: "<url>"
initrd: "<url>" # optional
File Organization
| Path | Purpose |
|---|---|
site.yml |
Main playbook entry point |
defaults/main.yml |
All OS/utility definitions and default config |
endpoints.yml |
Live image endpoint URLs |
user_overrides.yml |
Local overrides (not committed) |
templates/menu/*.ipxe.j2 |
~100 iPXE menu templates |
templates/disks/*.j2 |
Bootloader embedded scripts |
templates/pipxe/*.j2 |
Raspberry Pi Makefile templates |
tasks/*.yml |
14 Ansible task files |
vars/{debian,redhat,ubuntu}.yml |
Per-distro package lists |
script/ |
Build and release shell scripts |
Menu Hierarchy
menu.ipxe (main) → linux.ipxe → ubuntu.ipxe, fedora.ipxe, ...
→ bsd.ipxe → freebsd.ipxe, openbsd.ipxe, ...
→ live.ipxe → live-ubuntu.ipxe, ...
→ utils-*.ipxe
→ windows.ipxe
Menus chain via chain ${menu}.ipxe || goto error. Signature verification gates chaining when sigs_enabled is true.
Error Handling
- Ansible: Relies on default fail-fast behavior. No
block/rescue/always. Guard tasks withwhen:conditions. Use| default()to prevent undefined variable errors. - iPXE: Use
command || goto fallbackchains. Protocol degradation: HTTPS → HTTP → local boot. Always provide a:errorlabel that prompts the user. - Shell scripts: Use
set -eat the top of all scripts.
Adding a New Operating System
- Add entry to
releases:inroles/netbootxyz/defaults/main.yml. - Create
roles/netbootxyz/templates/menu/<distro>.ipxe.j2following existing templates. - The menu template is auto-discovered via
filetreeiteration — no registration needed. - Add the distro to the appropriate category menu (e.g.,
linux.ipxe.j2) if it needs a menu entry. - If using live images, add endpoint to
endpoints.yml. - Test:
ansible-playbook site.yml --syntax-check && ansible-lint -v roles/netbootxyz/tasks
Key Variables
boot_domain: Target domain for generated menus.boot_version: Version string for releases.site_name: Custom branding (defaults tonetboot.xyz).generate_menus/generate_disks: Enable/disable build components.sigs_enabled: Enable signature verification for menu chaining.live_endpoint: Base URL for live/rescue images.- Runtime variables:
${distro}_mirrorand${distro}_base_dirare auto-generated fromreleases:entries inboot.cfg.j2and available to all menu templates at boot time.
Git Workflow
development: Main development branch, default PR target.RC: Release candidate staging.master: Production releases.- Commit style: imperative mood, descriptive. Automated commits use
Version bump for ...format.