105487c090
Adds a fast, reproducible install path that unpacks a prebuilt AlmaLinux 9 node
rootfs onto the device (Anaconda liveimg) instead of resolving packages, with
per-host networking still templated after the unpack. Reuses the OptiPlex storage
vars so image and package installs lay disks out identically. Templates-only per
review; the rootfs build lives in the bootapi-images repo.
- kickstart/image.ks.tmpl: liveimg --url={{ .DistroVars.rootfs_tarball }};
%post renders per-host NetworkManager keyfiles from NetBox interface data
(the image is generic and liveimg overwrites /etc), hostname, puppet-initial
PUPPETCA_URL env, and the provisioned callback.
- kickstart/_storage.ks.tmpl: shared storage-block/storage-pre partials
(storage_mode / vg_grow); almalinux9.ks.tmpl now uses them (no behaviour
change).
- catalog/almalinux9-image.yaml (VM autopart) + optiplex-7080-image.yaml
(auto-nvme + vg_grow), rootfs_tarball -> artifactapi rootfs-images repo.
Rootfs tarball built+published by https://git.unkin.net/unkin/bootapi-images
(v* tag). Validated with bootapi validate + shellcheck; no bootapi code change.
Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
121 lines
6.4 KiB
Markdown
121 lines
6.4 KiB
Markdown
# Distro catalog
|
|
|
|
One YAML file per bootable OS. bootapi selects an entry for a NetBox host
|
|
(platform slug / OS family / `provision_template` override) and uses it to build
|
|
the iPXE kernel/initrd URLs and pick the kickstart template. Adding an OS is a
|
|
YAML + template change here — **no bootapi code change**.
|
|
|
|
## Fields
|
|
|
|
| Field | Required | Meaning |
|
|
|-------|----------|---------|
|
|
| `name` | yes | catalog key; also what a `provision_template` override matches |
|
|
| `match.platforms` | one of platforms/family | exact NetBox platform slugs |
|
|
| `match.family` | one of platforms/family | NetBox platform family (matches any version) |
|
|
| `kickstart` | yes | kickstart template name (`kickstart/<name>.ks.tmpl`) |
|
|
| `kernel_url` | yes | Go-template for the installer kernel URL |
|
|
| `initrd_url` | yes | Go-template for the installer initrd URL |
|
|
| `version_default` | no | version used when the platform slug carries none |
|
|
| `kernel_args` | no | extra iPXE kernel args |
|
|
| `vars` | no | named Go-template strings exposed to templates as `.DistroVars.<key>` |
|
|
|
|
`kernel_url`, `initrd_url` and `vars` values are rendered with:
|
|
`{{.ArtifactBase}}` (bootapi's `BOOTAPI_ARTIFACT_BASE_URL`), `{{.Version}}`,
|
|
`{{.Arch}}`, `{{.Hostname}}`, `{{.Platform}}`, `{{.OSFamily}}`.
|
|
|
|
## Shipped entries
|
|
|
|
- **almalinux9** — artifactapi `almalinux` remote, tree
|
|
`almalinux/<ver>/BaseOS/<arch>/os/`. Generic / VM default (autopart on `sda`).
|
|
- **fedora** — artifactapi `fedora` remote, tree
|
|
`fedora/releases/<ver>/Everything/<arch>/os/`.
|
|
- **optiplex-3050 / optiplex-3060 / optiplex-7080** — AlmaLinux 9 on the Dell
|
|
OptiPlex fleet. Same install tree and `almalinux9` kickstart template, but
|
|
each passes a `storage_mode` (and, for the 7080, `vg_grow`) var so the one
|
|
template lays disks out per model. Ported from the Cobbler profiles
|
|
`almalinux9-dell_3050 / _3060 / _7080`. See "Per-model variants" below.
|
|
|
|
## Per-model variants (Dell OptiPlex)
|
|
|
|
Different OptiPlex models need slightly different storage handling, so each is
|
|
its own catalog entry selecting the shared `almalinux9` kickstart with a
|
|
model-specific `storage_mode` var:
|
|
|
|
| Entry | `storage_mode` | Disk selection | Firmware | LVM PV |
|
|
|-------|----------------|----------------|----------|--------|
|
|
| `optiplex-3050` | `fixed-nvme` | static `nvme0n1` | legacy BIOS/MBR | fixed ~31G |
|
|
| `optiplex-3060` | `auto-nvme` | `%pre` picks first NVMe <512G | UEFI-aware (EFI part if booted UEFI) | fixed ~31G |
|
|
| `optiplex-7080` | `auto-nvme` + `vg_grow: "true"` | `%pre` picks first NVMe <512G | UEFI-aware | grows to fill disk |
|
|
|
|
The kickstart (`kickstart/almalinux9.ks.tmpl`) reads `.DistroVars.storage_mode`
|
|
/ `.DistroVars.vg_grow` and renders the matching storage stanza; any entry
|
|
without those vars (e.g. plain `almalinux9`, `fedora`) gets the generic
|
|
autopart-on-`sda` path.
|
|
|
|
**Model selection (NetBox-driven, no code change):** the entry `name` is the
|
|
OptiPlex **device_type slug**. Set the device's `provision_template` custom
|
|
field to that slug (`optiplex-3050` / `-3060` / `-7080`) and bootapi's catalog
|
|
`Select` picks the matching entry (override precedence beats platform/family).
|
|
The `match.platforms` slug on each entry is the device_type slug too — not a
|
|
real NetBox platform slug — so these entries are *only* reachable via the
|
|
override and never hijack a plain `almalinux9` host. To add another model, copy
|
|
one of these files, change the `name`/slug and `storage_mode`.
|
|
|
|
## Image (liveimg) installs
|
|
|
|
`image.ks.tmpl` unpacks a prebuilt rootfs tarball with Anaconda `liveimg` instead
|
|
of resolving packages — faster and reproducible. An image catalog entry looks
|
|
like a normal one but sets `kickstart: image` and a `rootfs_tarball` var:
|
|
|
|
```yaml
|
|
name: almalinux9-image
|
|
match: {platforms: [almalinux9-image]}
|
|
kickstart: image
|
|
kernel_url: "{{.ArtifactBase}}/almalinux/{{.Version}}/BaseOS/{{.Arch}}/os/images/pxeboot/vmlinuz" # the Anaconda installer kernel, unchanged
|
|
initrd_url: "...initrd.img"
|
|
vars:
|
|
rootfs_tarball: "https://artifactapi.k8s.syd1.au.unkin.net/api/v2/remotes/rootfs-images/files/almalinux9-node-<ver>.tar.zst"
|
|
# storage_mode / vg_grow work exactly as for package installs (omit for VM autopart).
|
|
```
|
|
|
|
- **Boot** is still the AlmaLinux installer kernel/initrd; `liveimg` only changes
|
|
the payload. **Storage** reuses the shared `kickstart/_storage.ks.tmpl` partials
|
|
(`storage_mode` / `vg_grow`), so image and package installs lay disks out
|
|
identically — including the OptiPlex NVMe modes (`optiplex-7080-image` shows an
|
|
image + `auto-nvme` + `vg_grow` combination).
|
|
- **Networking is templated per-host in `%post`** (NetworkManager keyfiles from
|
|
the same NetBox interface data), because the generic image has no per-host
|
|
identity and the `liveimg` unpack overwrites `/etc`.
|
|
- The tarball is built by the separate
|
|
[bootapi-images](https://git.unkin.net/unkin/bootapi-images) repo (a `v*` tag
|
|
builds and uploads `almalinux9-node-<ver>.tar.zst` to the artifactapi
|
|
`rootfs-images` local repo). Baked into the image = everything the `%post`
|
|
assumes present (kernel/grub/dracut, NetworkManager, openssh, chrony,
|
|
kexec-tools, curl, puppet-agent). Bump an image = new bootapi-images release +
|
|
a one-line `rootfs_tarball` edit here.
|
|
|
|
## Adding another distro (the intended path)
|
|
|
|
Add `catalog/<name>.yaml` + `kickstart/<name>.ks.tmpl`. If the OS lives on a
|
|
mirror bootapi can't already reach, add an artifactapi remote first
|
|
(terraform-artifactapi `config/remote_rpm/<name>.yaml`). CI (`bootapi validate`)
|
|
will render the new distro against a fixture host and fail the PR if anything is
|
|
unresolved.
|
|
|
|
### Debian / Talos — not implemented, different artifact shapes
|
|
|
|
These need their own catalog fields/template because their PXE artifacts differ
|
|
from the RHEL-family `images/pxeboot/{vmlinuz,initrd.img}` layout:
|
|
|
|
- **Debian**: netboot installer under
|
|
`dists/<release>/main/installer-<arch>/current/images/netboot/` with
|
|
`linux` + `initrd.gz`, and preseed (not kickstart). A `debian` entry would set
|
|
`kernel_url`/`initrd_url` to those paths and reference a `debian.preseed.tmpl`
|
|
template (and bootapi would serve it from `/ks` unchanged — it's just text).
|
|
- **Talos**: immutable OS booted from factory images (`vmlinuz` + `initramfs.xz`
|
|
from the Talos image factory / a mirrored remote), configured by a machine
|
|
config, not a kickstart. A `talos` entry would point `kernel_url`/`initrd_url`
|
|
at the factory artifacts and carry the config URL via `kernel_args`/`vars`.
|
|
|
|
Both are deferred; this note records the shape so the follow-up is mechanical.
|