bootapi

bootapi is a small Go service that replaces Cobbler's PXE/kickstart side. It renders kickstart files and iPXE boot scripts from NetBox device data and serves them over HTTP to PXE-booting hosts.

The ENC half of Cobbler already moved to encapi. With bootapi, provisioning a new host is:

  1. terraform the host into NetBox (device, interfaces/MACs, IP, platform, role) and encapi (classification), then
  2. rack it and let it PXE-boot — DHCP points it at bootapi, which serves the iPXE script and the rendered kickstart; the kickstart hands off to the existing Puppet firstrun bootstrap.

How it works

DHCP next-server ─▶ iPXE ─▶ GET /ipxe/<mac> ─▶ boot kernel+initrd, inst.ks=<bootapi>/ks/<host>
                                                        └▶ GET /ks/<host> ─▶ rendered kickstart ─▶ puppet firstrun

bootapi identifies the booting host by the MAC it booted from (NetBox interface lookup → device → primary IP, platform, role, interfaces), renders a Go text/template selected from the host's platform/role/custom-field, and serves it. Templates are embedded defaults, overridable from a directory (ConfigMap in k8s).

Endpoints (summary)

Path Purpose
GET /ipxe/{mac} · GET /boot/ipxe?mac= iPXE boot script
GET /ks/{ident} rendered kickstart (MAC or hostname)
POST /provisioned/{ident} end-of-kickstart callback (token) → clears pxe_enabled in NetBox
GET /healthz · /readyz · /metrics health + Prometheus

The boot path is served over plain HTTP (PXE installers have no internal-CA trust); HTTPS is offered in parallel. Unknown MAC → iPXE gets a safe fallback (local-disk boot, HTTP 200), never a 404; a host with pxe_enabled=false gets the same fallback so it won't re-install. Unknown kickstart host → 404. Full rationale in docs/endpoints.md.

Multi-distro + live templates

  • Distro catalog (catalog/*.yaml): each OS maps a NetBox platform/family to its boot images (artifactapi remotes), kernel args and kickstart template. Adding Fedora/Debian/Talos is a YAML + template change, no code change. Ships almalinux9 + fedora.
  • Template git-sync: bootapi pulls the bootapi-templates repo every 3m (like argocd) and hot-swaps the template set (last-good kept on a bad push); embedded defaults are the startup fallback.

Documentation

Configuration

Env-based (12-factor), see config.example.env. Key vars: BOOTAPI_NETBOX_URL, BOOTAPI_NETBOX_TOKEN[_FILE], BOOTAPI_BASE_URL, BOOTAPI_BOOT_BASE_URL, BOOTAPI_ROOT_PASSWORD_HASH[_FILE], BOOTAPI_UNKNOWN_MAC_FALLBACK.

Development

make build       # build ./bin/bootapi
make test-race   # go test -race ./...
make lint        # golangci-lint (v2) if installed, else go vet
make run         # build + run

CI (Woodpecker): pre-commit, golangci-lint v2 + go test -race, and a docker build on PRs; on a v* tag, a container image push and a Gitea binary release. Cut a release with make patch|minor|major (tags + pushes).

Layout

cmd/bootapi/         main
internal/config/     env config
internal/model/      Host/Interface data model (incl. pxe_enabled gate)
internal/netbox/     NetBox client (reads + pxe_enabled write) + TTL cache, behind an interface
internal/catalog/    distro catalog: NetBox host -> boot images/kickstart
internal/render/     text/template engine (swappable Set), selection, loader
internal/gitsync/    periodic git pull + atomic template reload (last-good)
internal/server/     chi HTTP handlers + Prometheus metrics
templates/           embedded defaults: kickstart, iPXE, catalog/*.yaml
docs/                see above
S
Description
PXE/kickstart boot service replacing Cobbler. Renders kickstart + iPXE from NetBox data over HTTP. Go API.
Readme 161 KiB
Languages
Go 90.9%
Go Template 6.8%
Makefile 2%
Dockerfile 0.3%