# 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](https://git.unkin.net/unkin/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/ ─▶ boot kernel+initrd, inst.ks=/ks/ └▶ GET /ks/ ─▶ 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](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 - [docs/endpoints.md](docs/endpoints.md) — the PXE flow, every endpoint, error/fallback behavior, metrics. - [docs/data-model.md](docs/data-model.md) — the exact template data model + NetBox custom fields + template selection. - [docs/template-authoring.md](docs/template-authoring.md) — writing/overriding kickstart & iPXE templates. - [docs/deployment.md](docs/deployment.md) — Kubernetes/argocd wiring, Vault secrets, and the DHCP cutover. - [docs/security.md](docs/security.md) — what belongs in NetBox vs Vault; secrets in kickstarts. ## Configuration Env-based (12-factor), see [`config.example.env`](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 ```bash 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 ```