Add image-based provisioning (liveimg) templates + catalog
ci/woodpecker/push/pre-commit Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/push/validate Pipeline was successful
ci/woodpecker/pr/validate Pipeline was successful

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
This commit is contained in:
2026-07-29 21:44:14 +10:00
parent 0e211893db
commit 105487c090
6 changed files with 310 additions and 94 deletions
+33
View File
@@ -61,6 +61,39 @@ 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
+22
View File
@@ -0,0 +1,22 @@
# Distro catalog entry: AlmaLinux 9, IMAGE install (liveimg).
#
# Boots the same AlmaLinux installer kernel/initrd as almalinux9, but the
# kickstart (image.ks.tmpl) uses liveimg to unpack the prebuilt node rootfs
# tarball instead of resolving packages -- much faster, reproducible. Generic
# storage (autopart on sda). Select via a device's provision_template custom
# field = "almalinux9-image".
name: almalinux9-image
match:
platforms: [almalinux9-image]
kickstart: image
version_default: "9"
kernel_url: "{{.ArtifactBase}}/almalinux/{{.Version}}/BaseOS/{{.Arch}}/os/images/pxeboot/vmlinuz"
initrd_url: "{{.ArtifactBase}}/almalinux/{{.Version}}/BaseOS/{{.Arch}}/os/images/pxeboot/initrd.img"
kernel_args:
- inst.text
- net.ifnames=0
vars:
# Prebuilt node rootfs on the artifactapi rootfs-images local repo, built and
# published by the bootapi-images repo (v* tag). Immutable, semver-versioned;
# bump this one line to roll the fleet forward (overwrites are 409-rejected).
rootfs_tarball: "https://artifactapi.k8s.syd1.au.unkin.net/api/v2/remotes/rootfs-images/files/almalinux9-node-1.0.0.tar.zst"
+21
View File
@@ -0,0 +1,21 @@
# Distro catalog entry: OptiPlex 7080, IMAGE install (liveimg).
#
# The image counterpart of optiplex-7080: same liveimg payload as
# almalinux9-image, but with the 7080's auto-NVMe / grow-to-fill storage
# (storage_mode auto-nvme + vg_grow). Proves the image kickstart reuses the
# OptiPlex model storage exactly as the package install does. Select via a
# device's provision_template custom field = "optiplex-7080-image".
name: optiplex-7080-image
match:
platforms: [optiplex-7080-image]
kickstart: image
version_default: "9"
kernel_url: "{{.ArtifactBase}}/almalinux/{{.Version}}/BaseOS/{{.Arch}}/os/images/pxeboot/vmlinuz"
initrd_url: "{{.ArtifactBase}}/almalinux/{{.Version}}/BaseOS/{{.Arch}}/os/images/pxeboot/initrd.img"
kernel_args:
- inst.text
- net.ifnames=0
vars:
rootfs_tarball: "https://artifactapi.k8s.syd1.au.unkin.net/api/v2/remotes/rootfs-images/files/almalinux9-node-1.0.0.tar.zst"
storage_mode: auto-nvme
vg_grow: "true"