# Deploying bootapi > The actual argocd-apps deployment is a **follow-up task** and is intentionally > not part of this repo. This document is the spec for that follow-up plus the > DHCP change the estate needs. bootapi is a stateless HTTP service. It mirrors encapi's deployment shape: a Go binary in a distroless image, config from env, secrets from Vault via the Vault Secrets Operator (VSO). ## Container image `git.unkin.net/unkin/bootapi:` (built + pushed by `.woodpecker/docker.yaml` on a `v*` tag). Also mirror to the artifactapi local docker registry if desired. ## Kubernetes wiring (argocd-apps follow-up) Create `apps/base/bootapi/` following the argocd-apps `AGENTS.md` pattern: 1. **namespace** `bootapi`. 2. **VaultAuth** (`default`) — kubernetes method, mount `k8s/au/syd1`, role `default`, SA `default` (copy netbox's `vaultauth.yaml`). 3. **VaultStaticSecret** → k8s Secret `bootapi-secrets`, from Vault kv path `kubernetes/namespace/bootapi/default/bootapi-secrets` with keys: - `netbox_token` — a **dedicated, read-only** NetBox API token for bootapi (create a `bootapi` NetBox user/token via terraform-netbox rather than reusing the seeded superuser token at `kv/kubernetes/namespace/netbox/default/netbox-superuser`). - `root_password_hash` — crypt(3) hash for the installed root account (the successor to Cobbler's eyaml `default_password_crypted`). - `ssh_authorized_keys` — optional, newline-separated. 4. **ConfigMap** `bootapi-templates` (optional) — override `*.ks.tmpl` / `*.ipxe.tmpl`, mounted at `BOOTAPI_TEMPLATE_DIR=/etc/bootapi/templates`. Omit to use the embedded defaults. Annotate the Deployment with `reloader.stakater.com/auto: "true"` so template edits roll the pods. 5. **Deployment** — image above, env from `config.example.env`, secret keys wired as `BOOTAPI_NETBOX_TOKEN_FILE`/`BOOTAPI_ROOT_PASSWORD_HASH_FILE` (mount the Secret) or `...FROM secretKeyRef`. Least-privilege securityContext (`runAsNonRoot`, `drop: [all]`). Baseline resources: requests `512Mi`/`1`, limits `2Gi`/`2` cpu. 6. **Service** `bootapi` (ClusterIP, port 80 → 8000) plus a **LoadBalancer** (or Gateway HTTPRoute) reachable by PXE clients at a stable address/hostname — this is what DHCP points at. Reuse the Vault-issued TLS the Cobbler vhost used if you terminate TLS at a gateway; note that iPXE fetches are plain HTTP, so a plain HTTP listener on the PXE VLAN is required either way. 7. Register in `argocd/applicationsets/platform.yaml` (`apps/overlays/*/bootapi`) and the platform AppProject destinations. ### Cross-repo dependencies (per estate conventions) - **argocd-apps**: add a `serviceaccount_*` under `apps/base/woodpecker/` if the bootapi pipelines need a dedicated SA (they use `default` today). - **terraform-vault**: add the k8s auth role + kv policy granting the `bootapi` namespace read on `kv/kubernetes/namespace/bootapi/default/*`. - **terraform-netbox**: create the read-only `bootapi` NetBox token and seed it (plus `root_password_hash`) into the Vault kv path above. ## DHCP change (the cutover) Cobbler advertised itself at anycast `198.18.19.19` as the DHCP `next-server`, with `filename "/ipxe.efi"` (UEFI arch 7/9) or `/undionly.kpxe` (BIOS arch 0). Today those are set in `puppet-prod` hieradata `hieradata/roles/infra/dhcp/server.yaml` (`pools.*.pxeserver` and the `UEFI-64`/`Legacy` dhcp classes). To cut a subnet over to bootapi, repoint DHCP for that pool: - `next-server` → bootapi's LB IP (or keep the `198.18.19.19` anycast and move the anycast advertisement to bootapi's node/LB). - `filename` → the iPXE binary as before (`/ipxe.efi` / `/undionly.kpxe`); bootapi does not serve the NBP itself. The chained iPXE must then be told to fetch bootapi's script — either bake `chain http:///ipxe/${net0/mac}` into the site iPXE binary/embedded script, or set DHCP option 67 to that URL for iPXE user-class requests. This replaces Cobbler's `chain http://${next-server}/cblr/svc/op/gpxe/mac/${net0/mac}`. Roll one pool at a time (the PXE subnets are `198.18.13.0/24`–`198.18.17.0/24`); Puppet autosign already trusts those subnets and `*.main.unkin.net`, so a host installed via bootapi checks in exactly as before.