unkin-agent a414918350
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Fetch templates over HTTP instead of shelling out to git
The runtime image is distroless and has no git binary, so every sync
failed and bootapi silently served the stale embedded templates.

- fetch the branch tarball (<repo>/archive/<branch>.tar.gz) and extract
  it into an in-memory FS; no checkout, no writable volume
- digest the extracted tree, not the archive bytes, so a recompressed
  identical archive is not a change
- skip entries that would escape the tree
- log the source commit from Gitea's immutable Link header
2026-09-26 18:59:07 +10:00

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 templates-tarball fetch + atomic 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 182 KiB
Languages
Go 91.3%
Go Template 6.5%
Makefile 1.9%
Dockerfile 0.3%